home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / p / portfoli / small_c / prg.man < prev    next >
Encoding:
Text File  |  1996-10-30  |  165.5 KB  |  5,160 lines

  1.           
  2.           
  3.           
  4.           
  5.           
  6.           
  7.           
  8.           
  9.           
  10.           
  11.           
  12.           
  13.                                                      ii
  14.                                                     iiii
  15.                                                      ii
  16.                          sss           cccc             
  17.                        ssssssss      cccccccc      iiiii
  18.                       sss    sss    ccc    ccc     iiiii
  19.                       sssss        ccc               iii
  20.                        sssss       ccc               iii
  21.                           sssss    ccc               iii
  22.                       sss    sss    ccc    ccc       iii
  23.                        ssssssss      cccccccc     iiiiiiiii
  24.                          ssss          cccc       iiiiiiiii
  25.           
  26.           
  27.                              Small C Interpreter
  28.                            Version 1.3 for MS-DOS
  29.                         Copyright (C) 1986 Bob Brodt
  30.           
  31.           
  32.                             Programmer's Manual
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.      Small C Interpreter                                Programmer's Manual
  62.  
  63.  
  64.      1. Introduction to SCI Programming 
  65.  
  66.  
  67.                This section of the manual is a tutorial introduction 
  68.           to the C language.  If you have a casual knowledge of BASIC 
  69.           and understand some of the fundamental concepts of 
  70.           programming, you should have no difficulty in following 
  71.           along.  This tutorial is designed to be used along with SCI, 
  72.           so get out your working copy of the SCI distribution 
  73.           diskette.  You did make a backup copy, didn't you?  If not, 
  74.           DO NOT PASS GO, DO NOT COLLECT $200 until you've read and 
  75.           followed the instructions in the Introduction section of the 
  76.           SCI User's Manual!  
  77.  
  78.                Now go ahead and start up SCI. The interpreter should 
  79.           be loading the default "shell" file, SHELL.SCI. This file 
  80.           simply contains a C program that is run by the SCI 
  81.           interpreter.  It performs several functions (most of which 
  82.           shall remain invisible to you for the moment), but the most 
  83.           important is to allow you to write and test SCI programs 
  84.           immediately.  After the interpreter has started up, you 
  85.           should see SCI's program identification banner and a 
  86.           greater-than symbol (>), like this: 
  87.  
  88.  
  89.                A> SCI
  90.                Small C Interpreter, V1.3 15Mar86 Copyright (C) 1986 Bob Brodt
  91.                Small C Shell, V1.3 15Mar86 Copyright (C) 1986 Bob Brodt
  92.                >
  93.  
  94.  
  95.                The ">" tells you that SCI is now ready to accept input 
  96.           from you.  One of the nicest features of SCI is its ability 
  97.           to immediately perform any C statement that you type.  As 
  98.           you will learn later, every C statement produces a value as 
  99.           a side-effect.  One of the functions of SHELL.SCI is to 
  100.           print this value as a decimal number after the statement has 
  101.           been executed.  Thus, you could enter some arithmetic 
  102.           expression like the following: 
  103.  
  104.  
  105.                > 2+2;
  106.                4
  107.                >
  108.  
  109.  
  110.                and have the SCI shell print the result, just like 
  111.           BASIC.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.                                      - 1 -
  119.  
  120.  
  121.      Small C Interpreter                                Programmer's Manual
  122.  
  123.  
  124.      2. SCI Statement Structure 
  125.  
  126.  
  127.                In the above example, notice the semicolon at the end 
  128.           of the line.  The C language allows you to write programs 
  129.           without regard to "white space" (spaces, tabs and ends of 
  130.           lines).  This means that the components of program 
  131.           statements can be seperated by as many spaces or tabs as you 
  132.           like; program lines can be grouped together seperated from 
  133.           the rest of the program by blank lines, to show the reader 
  134.           that they perform a discrete function; you can indent groups 
  135.           of lines following a program looping statement to show where 
  136.           the loop starts and ends.  By allowing you to "sculpture" 
  137.           your program like this, C lets you write very easy to read 
  138.           and understand programs.  This is very much in contrast to 
  139.           BASIC which requires every program statement to start with a 
  140.           line number, followed by a space and then the statement all 
  141.           on a single line.  Because C is such a free-form language it 
  142.           would have a difficult time recognizing the end of a 
  143.           statement without some kind of "end-of-statement" marker.  
  144.           This is the purpose of the semicolon.  
  145.  
  146.                Now we're going to confuse you even further by telling 
  147.           you that SCI doesn't need a semicolon at the end of a 
  148.           statement!  Because it's an interpreter, SCI recognizes 
  149.           either the end of a line or a semicolon as an 
  150.           end-of-statement marker.  In fact, if a statement spills 
  151.           over onto another program line, SCI will complain - it 
  152.           requires that every statement be completely contained on one 
  153.           line.  This restriction was imposed by the fact that SCI is 
  154.           an interpreter and not a compiler.  This is an important 
  155.           difference between "SCI C" and "standard C" (which allows a 
  156.           single statement to be spread out over several lines).  So 
  157.           if you are an experience "C hacker", please be aware of this 
  158.           fact.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.                                      - 2 -
  179.  
  180.  
  181.      Small C Interpreter                                Programmer's Manual
  182.  
  183.  
  184.      3. SCI Program Structure 
  185.  
  186.  
  187.                When learning a new programming language, it's always 
  188.           helpful to recall fundamentals and ask yourself the question 
  189.           "what is a program?".  Simply stated, a program is a list of 
  190.           instructions that tell the computer exactly what to do.  A 
  191.           program written in the BASIC language is an ideal example of 
  192.           this concept; a list of instructions.  The instructions are 
  193.           numbered to make it easy to see the order in which they'll 
  194.           be performed.  Let's examine a fragment from a BASIC program 
  195.           and identify some of its key components.  
  196.  
  197.  
  198.                100 REM *** sort a list of numbers in ascending order ***
  199.                110 DIM NUM(100),RSP$(80)
  200.                120 REM get the unsorted number list
  201.                     .
  202.                     .
  203.                     .
  204.                220 REM got 'em, now sort 'em then print 'em
  205.                230 GOSUB 500
  206.                240 FOR I=1 TO 100
  207.                250    PRINT NUM(I)
  208.                260 NEXT I
  209.                270 PRINT "Got another list to sort?";
  210.                280 INPUT RSP$
  211.                290 IF RSP$="Y" THEN GOTO 120
  212.                300 END
  213.                500 REM *** bubble sort routine ***
  214.                510 REM sorts the numbers in the array "NUM"
  215.                     .
  216.                     .
  217.                     .
  218.                600 RETURN
  219.  
  220.  
  221.                Even the novice BASIC programmer can glance at this 
  222.           program fragment and tell what's happening: it starts with 
  223.           line 100, which is a note to the (human) reader telling him 
  224.           what the program intends to do - sort a bunch of numbers in 
  225.           ascending order.  Line 110 tells the computer to reserve 
  226.           some memory storage we'll need later.  Remember that BASIC 
  227.           allows variables to be "known" to every instruction in the 
  228.           program.  Thus, you (the programmer) can not effectively 
  229.           control and limit access to variables.  This makes it 
  230.           difficult at times to determine where in the program a 
  231.           variable is being set when it shouldn't be.  This is a very 
  232.           important difference between BASIC and C, as you will find 
  233.           out later.  
  234.  
  235.                The word "GOSUB" at line 230 tells the computer to hold 
  236.  
  237.  
  238.                                      - 3 -
  239.  
  240.  
  241.      Small C Interpreter                                Programmer's Manual
  242.  
  243.  
  244.           its place at the current location in the program, then jump 
  245.           to instruction number 500.  The "RETURN" at line 600 
  246.           corresponds to the "GOSUB" and tells the computer to 
  247.           continue with the instruction following the "GOSUB". Notice 
  248.           that the set of instructions from line 500 to 600 are 
  249.           general-purpose in nature and could possibly be used in 
  250.           another BASIC program that required a number sorting 
  251.           function.  However, to interface this sub-program to another 
  252.           program would probably require modifications to either the 
  253.           other program or the sub-program, or both.  This makes the 
  254.           thought of extracting the number sorting function somewhat 
  255.           less attractive.  
  256.  
  257.                Now look at the instructions from line 270 to 290. 
  258.           Essentially, these ask the program user if there are any 
  259.           more numbers to sort, and jump back to the beginning of the 
  260.           program to start the process all over again.  But, what if 
  261.           the programmer decides at some later time to modify the 
  262.           program and accidentally deletes line 120 - the target of 
  263.           the "GOTO" instruction at 290. BASIC would be totally 
  264.           confused, since it wouldn't be able to find line 120 
  265.           anymore.  Although numbering program instructions, like 
  266.           BASIC does, is very nice and neat and makes a program easy 
  267.           for the human reader to follow, it can become unmanageable 
  268.           as the program grows in complexity.  
  269.  
  270.                Now let's take a look at the comparable program 
  271.           fragment written in C.  Please don't be concerned with the 
  272.           details of this program at the moment, but rather focus on 
  273.           the overall structure: 
  274.  
  275.  
  276.                # *** sort a list of numbers in ascending order ***
  277.                main()
  278.                {
  279.                     char num[100], rsp[80];
  280.                
  281.                     while ( 1 )
  282.                     {
  283.                          # get the unsorted number list
  284.                               .
  285.                               .
  286.                               .
  287.                          # got 'em, now sort 'em then print 'em
  288.                          sort( num );
  289.                          i=0;
  290.                          while ( i<100 )
  291.                          {
  292.                               printf( "%d\n", num[i] );
  293.                               ++i;
  294.                          }
  295.                          puts( "Got another list to sort?" );
  296.  
  297.  
  298.                                      - 4 -
  299.  
  300.  
  301.      Small C Interpreter                                Programmer's Manual
  302.  
  303.  
  304.                          gets( rsp )
  305.                          if ( rsp[0] != 'Y' )
  306.                               break;
  307.                     }
  308.                }
  309.                sort( numlist )
  310.                char numlist[];
  311.                {
  312.                     # bubble sort routine
  313.                          .
  314.                          .
  315.                          .
  316.                }
  317.  
  318.  
  319.                The first thing that strikes the BASIC programmer when 
  320.           he looks at a C program is the absence of line numbers!  The 
  321.           C language relies purely on the location of statements 
  322.           within a program to determine the order of program 
  323.           execution.  
  324.  
  325.                In the above example, notice the presence of the 
  326.           matching left and right curly braces ({ and }). These serve 
  327.           to bind together logical sections of the program.  In 
  328.           particular, notice the first "{" (following "main()") and 
  329.           its partner towards the end of the program.  These 
  330.           particular matching braces are used to "bind" everything 
  331.           between them to make one functional unit.  This functional 
  332.           unit is called a "function" in C.  Each function can be 
  333.           thought of as an autonomous entity - everything within the 
  334.           function is accessible only to statements within that 
  335.           function.  The name of the function can be found immediately 
  336.           before the first "{", in this case, the function's name is 
  337.           "main". Another function can be found towards the end of the 
  338.           program, its name is "sort".  
  339.  
  340.                So, in contrast to BASIC, a C program is a collection 
  341.           of these modular functions rather than just a sequential 
  342.           list of instructions.  
  343.  
  344.  
  345.  
  346.  
  347.  
  348.  
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356.  
  357.  
  358.                                      - 5 -
  359.  
  360.  
  361.      Small C Interpreter                                Programmer's Manual
  362.  
  363.  
  364.      4. Functions 
  365.  
  366.  
  367.                Think of functions as a kind of "black box" machine; 
  368.           raw materials, in the form of information, goes into one end 
  369.           of the machine and a final product comes out of the other 
  370.           end.  The inner workings of the machine are hidden and we 
  371.           don't really care to know how the machine works, as long as 
  372.           the final product is what we expected from the raw materials 
  373.           supplied.  
  374.  
  375.                In C, the "raw materials" passed to a function are 
  376.           known as the function's "arguments" and the "final product" 
  377.           is called the function's "return value".  C allows you to 
  378.           pass as many arguments to a function as needed, but the 
  379.           function always returns one and only one value.  In the 
  380.           section on Variables we will see how a function can be made 
  381.              ____                                             to seem to return more than one value.  
  382.  
  383.                To get SCI to execute the statements within a 
  384.           particular function, all you have to do is mention the 
  385.           function's name.  In the program fragment shown above, you 
  386.           would type either "main()", or "sort()" at the SCI prompt.  
  387.           The parentheses following a function's name serve two 
  388.           purposes: they distinguish the entity as being the name of a 
  389.           function as opposed to a variable; and they show SCI where 
  390.           the function's arguments start and end.  If a function does 
  391.           not require any arguments (as in "main()" above), you still 
  392.           need to supply the left and right parentheses.  If a 
  393.           function requires more than one argument, each argument is 
  394.           seperated from the preceding one with a comma (,) like so: 
  395.  
  396.  
  397.                func( 23, 15, 34 )
  398.  
  399.  
  400.                Note that the spaces are optional!  
  401.  
  402.  
  403.      4.1. Library Functions 
  404.  
  405.  
  406.                Beyond using it as a rather dumb integer calculator, 
  407.           you can use the SCI shell to test out any valid C statement 
  408.           with support from a large collection of built-in functions.  
  409.           As you work through this tutorial, you will be introduced to 
  410.           many of these, refered to hereafter as "Library Functions" 
  411.           (see the section on Library Functions for more details).  
  412.           You may, if you like, think of the Library Functions as 
  413.           being analogous to BASIC's built-in commands like "PRINT" 
  414.           and "INPUT". Most of the Library Functions are similar to 
  415.           those shipped with "industrial strength" C compilers, so 
  416.  
  417.  
  418.                                      - 6 -
  419.  
  420.  
  421.      Small C Interpreter                                Programmer's Manual
  422.  
  423.  
  424.           many of the programs you write under SCI should be 
  425.           transportable with some minor changes.  
  426.  
  427.  
  428.      4.1.1. putd() 
  429.  
  430.  
  431.                The Library Function "putd()" prints a number, or the 
  432.           results of a calculation on the console screen.  Try 
  433.           entering the following commands from the shell: 
  434.  
  435.  
  436.                putd(123)
  437.                putd( 235 + 12370 )
  438.  
  439.  
  440.                In the first example, the argument passed to "putd()" 
  441.           is the number 123.  The function should have printed "123" 
  442.           on the console screen.  In the second example, the argument 
  443.           is the sum of 235 and 12370. Note that this calculation is 
  444.           performed first, then the result is passed to "putd()" for 
  445.           printing.  
  446.  
  447.                Below the numbers that were printed by "putd()" you 
  448.           should have seen a zero printed as well.  This zero is the 
  449.           value returned by "putd()" and was printed by the shell.  In 
  450.           this case, the return value of a function was not 
  451.           particularly useful.  We were more interested in the 
  452.           side-effect of this function, namely the displaying of a 
  453.           number on the screen.  
  454.  
  455.  
  456.      4.1.2. getchar() 
  457.  
  458.  
  459.                The Library Function "getchar()" waits for a single 
  460.           keyboard key to be pressed, then returns the value (in 
  461.           ASCII) of that key.  At the shell prompt, try typing 
  462.           "getchar()", hit a carriage return and then hit the letter 
  463.           'a' key.  You should see the number 97 printed by the shell, 
  464.           the ASCII value in decimal of the character 'a'.  
  465.  
  466.                Unlike "putd()", this function required no arguments 
  467.           and returned a useful value.  
  468.  
  469.  
  470.      4.1.3. puts() 
  471.  
  472.  
  473.                The function "puts()" is used to print a sequence of 
  474.           characters (known in C jargon as a "string") on the 
  475.           console.  A string is represented in C as a bunch of 
  476.  
  477.  
  478.                                      - 7 -
  479.  
  480.  
  481.      Small C Interpreter                                Programmer's Manual
  482.  
  483.  
  484.           characters enclosed in quotes ("), just as in BASIC. Try the 
  485.           following command, and be careful to type the string exactly 
  486.           as it appears here: 
  487.  
  488.  
  489.                puts("hello, world\n")
  490.  
  491.  
  492.                Look closely at the string again and notice the 
  493.           backslash (\) just before the letter 'n'. This two-character 
  494.           combination (\n) is standard C shorthand notation for a 
  495.           "newline" character.  Newlines have the effect of performing 
  496.           a cariage return plus linefeed on the console.  Had we 
  497.           omitted the "\n" from the string, "puts()" would have just 
  498.           printed "hello, world" and left the cursor on the same line, 
  499.           after the "d" in "world".  SCI provides other similar 
  500.           shorthand notations, which will be explained in a later 
  501.           section.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.                                      - 8 -
  539.  
  540.  
  541.      Small C Interpreter                                Programmer's Manual
  542.  
  543.  
  544.      5. Your First Programs 
  545.  
  546.  
  547.                Now it's time to write your first program.  If you 
  548.           haven't already done so, read the Editor section of the 
  549.           User's Manual and perform the installation as required for 
  550.           your particular computer.  If you are unsuccessful in 
  551.           getting the editor to work properly, you can create the 
  552.           sample programs with your favorite text editor, then start 
  553.           up SCI and load the program file.  This will be tedious and 
  554.           time consuming, but it may just give you enough 
  555.           understanding of C to perform the editor installation 
  556.           properly.  If all else fails, appeal to the author for 
  557.           help!  
  558.  
  559.  
  560.      5.1. Hello again, world!  
  561.  
  562.  
  563.                Either using the built-in editor or a seperate text 
  564.           editor, create the following program: 
  565.  
  566.  
  567.                hi()
  568.                {
  569.                     puts("hello, world\n");
  570.                }
  571.  
  572.  
  573.                Now, from the shell, type the name of the function, 
  574.           "hi()". You should see the following on your screen: 
  575.  
  576.  
  577.                > hi()
  578.                hello world
  579.                0
  580.                >
  581.  
  582.  
  583.                If instead you are rewarded with an error message 
  584.           followed by a question mark, you did something wrong!  Hit a 
  585.           carriage return or two to get back to the shell's ">" 
  586.           prompt, go back into the editor, fix the mistake and try it 
  587.           again.  
  588.  
  589.                Whether you realize it or not, this exercise is an 
  590.           important first step for learning a new programming 
  591.           language.  It teaches you all of the routine motions you 
  592.           will be going through to write programs and gives you 
  593.           confidence to continue on.  
  594.  
  595.  
  596.  
  597.  
  598.                                      - 9 -
  599.  
  600.  
  601.      Small C Interpreter                                Programmer's Manual
  602.  
  603.  
  604.      5.2. Fahrenheit to Celsius 
  605.  
  606.  
  607.                Next, type in the following sample program: 
  608.  
  609.  
  610.                fahr(celsius)
  611.                {
  612.                     return 9 * celsius / 5 + 32;
  613.                }
  614.  
  615.  
  616.                This is a simple celsius to fahrenheit temperature 
  617.           conversion function.  Notice here the symbols for 
  618.           multiplication (*) and division (/) are the same as in most 
  619.           other programming languages.  
  620.  
  621.                Try executing this function with a few different 
  622.           celsius values.  Each time the argument is converted to 
  623.           fahrenheit and is returned to the shell to be printed.  
  624.  
  625.                As an exercise, modify the program to print the 
  626.           fahrenheit value and return a value of zero!  
  627.  
  628.  
  629.  
  630.  
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.                                      - 10 -
  659.  
  660.  
  661.      Small C Interpreter                                Programmer's Manual
  662.  
  663.  
  664.      6. Statements: Simple and Compound 
  665.  
  666.  
  667.                In C, a "statement" is just what you might expect; an 
  668.           imperative instruction to the computer to perform some 
  669.           calculation.  Statements are generally some kind of 
  670.           arithmetic expression followed by a semicolon (or the end of 
  671.           line in SCI) - we have encountered them before.  The C 
  672.           language also allows you to group together several of these 
  673.           "simple" statements and treat them as a single "compound" 
  674.           statement.  This is done by placing left and right curly 
  675.           braces ({ and }) around the simple statements.  Let's look 
  676.           at the example below: 
  677.  
  678.  
  679.                {puts("hello");puts("world\n");}
  680.  
  681.  
  682.                Here, everything within the left and right braces and 
  683.           the braces themselves are treated as a single statement in 
  684.           C.  The C language also lets us write the above statement 
  685.           like this: 
  686.  
  687.  
  688.                {
  689.                     puts( "hello" );
  690.                     puts( "world\n" );
  691.                }
  692.  
  693.  
  694.                Notice that the program becomes much easier to read 
  695.           when each statement is written on a seperate line.  Also 
  696.           notice that we have indented the two simple statements from 
  697.           the braces.  Indenting is the accepted way of conveying the 
  698.           intended structure of a program.  We are in effect saying 
  699.           that these two lines "belong together" and should be treated 
  700.           as a single unit.  
  701.  
  702.                The compound statement in the above example was 
  703.           obviously created for demonstration purposes only.  If it 
  704.           had been encountered by itself in a real program, the braces 
  705.           would have been superfluous and would not have altered the 
  706.           behavior of the program.  However, earlier we encountered an 
  707.           instance where the curly braces were required, namely 
  708.           immediately following a function definition.  Later on when 
  709.           we discuss program flow control, we will again sing the 
  710.           praises of compound statements.  
  711.  
  712.                We will now make just one more point concerning 
  713.           compound statements and the SCI shell.  From the shell, type 
  714.           the following two statements: 
  715.  
  716.  
  717.  
  718.                                      - 11 -
  719.  
  720.  
  721.      Small C Interpreter                                Programmer's Manual
  722.  
  723.  
  724.                > puts("hello"); puts(" world");
  725.                > {puts("hello"); puts(" world);}
  726.  
  727.  
  728.                In the first instance, you saw that only the word 
  729.           "hello" was printed followed by the shell's ">" prompt.  
  730.           This is because the interpreter executes only the first 
  731.           statement it finds in the input line buffer.  Since a 
  732.           statement is terminated by a semicolon, the second call to 
  733.           "puts" was never seen.  In the second example, the 
  734.           interpreter saw the left curly brace, recognized the entire 
  735.           line as a single statement, and executed both calls to 
  736.           "puts()".  
  737.  
  738.  
  739.      6.1. Comment Statements 
  740.  
  741.  
  742.                Comment statements are completely ignored by C and may 
  743.           be used liberally anywhere within a program for 
  744.           documentation purposes.  Standard C uses the two-character 
  745.           combinations /* (pronounced "slash-star") and */ to mark the 
  746.           beginning and ending of comment statements: 
  747.  
  748.  
  749.                2 + /* this is a comment */ 2 + 2;
  750.  
  751.  
  752.                The /* and */ need not necessarily be on the same 
  753.           program line, as for example: 
  754.  
  755.  
  756.                2 + 2 + 2;
  757.                /*
  758.                this is a comment
  759.                */
  760.  
  761.  
  762.                SCI uses the number symbol (#) to introduce comment 
  763.           statements.  A comment in SCI begins with a # and ends at 
  764.           the end of the line.  Being an interpreter, SCI required 
  765.           that comments appear on a single line, so only a comment 
  766.           start symbol was required.  The above example might appear 
  767.           in SCI like this: 
  768.  
  769.  
  770.                2 + 2 + 2;
  771.                #
  772.                # this is a comment
  773.                #
  774.  
  775.  
  776.  
  777.  
  778.                                      - 12 -
  779.  
  780.  
  781.      Small C Interpreter                                Programmer's Manual
  782.  
  783.  
  784.                Be careful when placing comments because everything to 
  785.           the right of the first # symbol on the line is ignored by 
  786.           SCI.  
  787.  
  788.  
  789.                2 + # this is a comment # 2 + 2;
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.                                      - 13 -
  839.  
  840.  
  841.      Small C Interpreter                                Programmer's Manual
  842.  
  843.  
  844.      7. Expressions 
  845.  
  846.  
  847.                Expressions can be thought of as components of a C 
  848.           statement - the values and operators that, when evaluated, 
  849.           yield a result.  The most common example that comes to mind 
  850.           are arithmetic expressions: 
  851.  
  852.  
  853.                2 + 3 - 5
  854.  
  855.  
  856.                An expression becomes a statement if we simply tack a 
  857.           semicolon at the end of it, thus: 
  858.  
  859.  
  860.                2 + 3 - 5;
  861.  
  862.  
  863.  
  864.      7.1. Operators 
  865.  
  866.  
  867.                Since C provides a plethora of operators, we will not 
  868.           discuss them all in this section but rather introduce them 
  869.           as they become relavent to the discussion.  If you have 
  870.           burning desire to discover all of C's operators, see the 
  871.           Appendix.  First, we will define some commonly used terms.  
  872.  
  873.  
  874.      7.1.1. Binary Operators 
  875.  
  876.  
  877.                The term "binary operator" does not refer to bits and 
  878.           bytes but rather to the class of operators that require two 
  879.           (hence "binary") operands.  Some of these you have probably 
  880.           already seen if you are familiar with other programming 
  881.           languages, like the addition (+), subtraction (-), 
  882.           multiplication (*) and division (/) operators.  
  883.  
  884.  
  885.      7.1.2. Unary Operators 
  886.  
  887.  
  888.                Unary operators perform their functions on only one 
  889.           operand.  The subtraction symbol (-) is used as a unary 
  890.           operator when it stands in front of a number or a variable, 
  891.           like so: 
  892.  
  893.  
  894.                -45
  895.  
  896.  
  897.  
  898.                                      - 14 -
  899.  
  900.  
  901.      Small C Interpreter                                Programmer's Manual
  902.  
  903.  
  904.                You may also use the plus sign (+) as a unary operator, 
  905.           although it would be superfluous since all numbers are 
  906.           assumed to be positive unless preceeded by a minus sign.  C 
  907.           also provides other unary operators that will be discussed 
  908.           later.  
  909.  
  910.  
  911.      7.2. Precedence 
  912.  
  913.  
  914.                If you will recall, in your high school algebra class 
  915.           you learned that in an arithmetic expression containing a 
  916.           combination of addition, subtraction, division and 
  917.           multiplication, the division and multiplication are always 
  918.           done before addition and subtraction.  That is to say that 
  919.           division and multiplication "take precedence" over addition 
  920.           and subtraction.  This property of precedence extends to all 
  921.           operators in the C language, not just the arithmetic 
  922.           operators.  
  923.  
  924.                You may defeat the normal order of evaluation of an 
  925.           expression by using parentheses, just as in modern algebra: 
  926.  
  927.  
  928.                (2 + 3) * 5
  929.  
  930.  
  931.                This will perform the addition first, then the 
  932.           multiplication.  You may use as many matched sets of 
  933.           parentheses as necessary to disambiguate the order of 
  934.           evaluation: 
  935.  
  936.  
  937.                (  ( (2+3) / 2 ) * 5  )
  938.  
  939.  
  940.                In fact, it is a good idea to use parentheses liberally 
  941.           whenever you are unsure of operator precedence.  
  942.  
  943.  
  944.      7.3. Associativity 
  945.  
  946.  
  947.                You also learned (hopefully in the same algebra class) 
  948.           that expressions are always evaluated from left to right.  
  949.           This same rule applys to expressions in C. This property of 
  950.           operators is known as associativity.  In C, most of the 
  951.                                          ____ ____ __ _____                        binary operators are evaluated from left to right, while the 
  952.                                              _____ __ ____               unary operators are evaluated from right to left.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.                                      - 15 -
  959.  
  960.  
  961.      Small C Interpreter                                Programmer's Manual
  962.  
  963.  
  964.      7.4. Arithmetic operators 
  965.  
  966.  
  967.                Now we are finally prepared to formally introduce C's 
  968.           arithmetic operators.  They are listed here in order of 
  969.           decreasing precedence: 
  970.  
  971.  
  972.                * / %   multiplication, division and modulo
  973.                + -     addition and subtraction
  974.  
  975.  
  976.                Most of these should already be familiar to you.  The 
  977.           modulo operator (%) gives the remainder from the division of 
  978.           the left value by the right value.  For example, the result 
  979.           of: 15 % 8 is 7.  
  980.  
  981.  
  982.      7.5. Bitwise Operators 
  983.  
  984.  
  985.                C also offers these bit-manipulation operators (again 
  986.           listed in decreasing precedence): 
  987.  
  988.  
  989.                << >>   left and right SHIFT
  990.                &   bitwise AND
  991.                ^   bitwise exclusive OR
  992.                |   bitwise OR
  993.  
  994.  
  995.                If you have a need to do bit manipulation but are not 
  996.           familiar with the above terms (SHIFT, AND, OR and exclusive 
  997.           OR), you should probably consult a textbook on computer 
  998.           programming since this is beyond the scope of this 
  999.           tutorial.  
  1000.  
  1001.                We will be learning more about other C operators in 
  1002.           later discussions.  
  1003.  
  1004.  
  1005.  
  1006.  
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016.  
  1017.  
  1018.                                      - 16 -
  1019.  
  1020.  
  1021.      Small C Interpreter                                Programmer's Manual
  1022.  
  1023.  
  1024.      8. Variables 
  1025.  
  1026.  
  1027.                Previously, we had only eluded to the fact that C does 
  1028.           allow you to create named data storage locations (a.k.a. 
  1029.           "variables"), now we will formally introduce you to all of 
  1030.           C's data types.  
  1031.  
  1032.                Except for the pre-defined Library Functions and the 
  1033.           editor's system-variables (which are found in SHELL.SCI), 
  1034.           all variables must first be made known to the program before 
  1035.           they may be used.  Unlike BASIC where a variable comes into 
  1036.           existance the very first time it is used in a statement, C 
  1037.           requires that every variable be formally declared before you 
  1038.           may use it within your program.  This section will cover the 
  1039.           fundamentals of C variable declarations.  
  1040.  
  1041.  
  1042.      8.1. Naming Conventions 
  1043.  
  1044.  
  1045.                The precise rules governing the naming of variables 
  1046.           usually varies from one C compiler to another.  The rules 
  1047.           for SCI variable names are as follows: 
  1048.  
  1049.  
  1050.                1) a variable name may contain any number of characters 
  1051.                     from the set of: 
  1052.  
  1053.  
  1054.                          1) the letters "a" through "z" and "A" 
  1055.                               through "Z".  
  1056.  
  1057.                          2) the underscore (_).  
  1058.  
  1059.                          3) the digits "0" through "9".  
  1060.  
  1061.  
  1062.                2) the first character of a variable must not be a 
  1063.                     digit (i.e. it must be either a letter or an 
  1064.                     underscore).  
  1065.  
  1066.                3) the case of a letter is significant, for example: 
  1067.                     "foobar" is not the same as "Foobar" or "FooBar".  
  1068.  
  1069.                4) although a variable may be as long as you like, only 
  1070.                     the first eight characters are signifcant.  For 
  1071.                     example: "return_value" and "return_value_1" refer 
  1072.                     to the same variable, since only the first eight 
  1073.                     characters ("return_v") are significant.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.                                      - 17 -
  1079.  
  1080.  
  1081.      Small C Interpreter                                Programmer's Manual
  1082.  
  1083.  
  1084.      8.2. Data Types 
  1085.  
  1086.  
  1087.                The C language supports many different types of 
  1088.           variables.  The most notable difference between them is the 
  1089.           amount of memory storage each one addresses.  The least 
  1090.           amount of memory a variable can represent depends on the 
  1091.           type of computer the program is written for.  Typically, 
  1092.           this is a byte of information, although some mainframe 
  1093.           machines do not have the capability to access memory in 
  1094.           smaller than 2 or 4 byte gobbles.  Most personal computers, 
  1095.           however can access memory one byte at a time and in C, this 
  1096.           data type is known as the "char", short for "character".  
  1097.  
  1098.  
  1099.      8.2.1. Char 
  1100.  
  1101.  
  1102.                A "char" variable in SCI is one byte long and can 
  1103.           represent a number between -128 and +127.  In order to make 
  1104.           a variable known to the program we must first declare it, so 
  1105.           to declare a "char" variable named "foobar" we would write: 
  1106.  
  1107.  
  1108.                char foobar;
  1109.  
  1110.  
  1111.                We can also declare more than one variable of the same 
  1112.           type on the same line by seperating each with a comma, like 
  1113.           so: 
  1114.  
  1115.  
  1116.                char foobar, snafu, gurgle;
  1117.  
  1118.  
  1119.  
  1120.      8.2.2. Int 
  1121.  
  1122.  
  1123.                Another variable type is the "int", short for 
  1124.           "integer". Again, the amount of memory an "int" addresses is 
  1125.           machine dependent.  In SCI, an "int" addresses two bytes of 
  1126.           memory, and can represent a number between -32768 and 
  1127.           +32767.  "Int"s are declared in a manner similar to "char"s: 
  1128.  
  1129.  
  1130.                int foobar;
  1131.                int snafu, wowbagger;
  1132.  
  1133.           Standard C also defines other data types such as floating 
  1134.           point variables, double precision integer and double 
  1135.           precision floating point.  You may also define your own data 
  1136.  
  1137.  
  1138.                                      - 18 -
  1139.  
  1140.  
  1141.      Small C Interpreter                                Programmer's Manual
  1142.  
  1143.  
  1144.           types that are a combination of these primaries (known as 
  1145.           "structures").  Unfortunately, these are all not supported 
  1146.           by this version of SCI.  
  1147.  
  1148.  
  1149.      8.3. Scope 
  1150.  
  1151.  
  1152.                If you are familiar with BASIC, then you already know 
  1153.           that a BASIC program variable is "known" throughout the 
  1154.           program - that is, any statement within the program may 
  1155.           alter a variable's contents.  This "feature" can lead to 
  1156.           some very difficult to find programming bugs.  For instance, 
  1157.           you may use a variable as a temporary loop counter in one 
  1158.           section of the program, only to discover later that you had 
  1159.           already decided to use that variable for another purpose and 
  1160.           its contents were continually being destroyed.  Ideally, we 
  1161.           would like to be able to use variable names indiscriminantly 
  1162.           in one section of a program without having to worry about 
  1163.           whether the variable name is being used in another section 
  1164.           of the program.  Happily, the C language offers this ability 
  1165.           as you will soon see.  This concept of limited (or rather 
  1166.           "controlled") access to variables is known as "scope".  
  1167.  
  1168.  
  1169.      8.3.1. Global Variables 
  1170.  
  1171.  
  1172.                In C, you may create variables that are known 
  1173.           throughout the program, just like in BASIC.  Variables that 
  1174.           have this property are known as "globals" and just like 
  1175.           BASIC, every statement within the program may retrieve and 
  1176.           store the value of a global variable.  A variable will 
  1177.           attain global status if it was declared outside of any curly 
  1178.           braces ({ and }) that delimit the body of a function.  Here 
  1179.           is an example to illustrate: 
  1180.  
  1181.  
  1182.                char c;            # "c" is a global
  1183.                int i, j;          # and so are "i" and "j"
  1184.                
  1185.                a_function()       # the first function in the program
  1186.                {
  1187.                     .
  1188.                     .
  1189.                     .
  1190.                }
  1191.                
  1192.                char flag, nyuk;   # some more global variables
  1193.                
  1194.                another_function() # another function
  1195.                {
  1196.  
  1197.  
  1198.                                      - 19 -
  1199.  
  1200.  
  1201.      Small C Interpreter                                Programmer's Manual
  1202.  
  1203.  
  1204.                     .
  1205.                     .
  1206.                     .
  1207.                }
  1208.  
  1209.  
  1210.                As you can see, C does not care where within a program 
  1211.           a global variable is declared as long as the declaration 
  1212.           appears outside of any functions.  
  1213.  
  1214.                SCI ensures that global variables are always set to 
  1215.           zero before the program starts up.  This is pretty much 
  1216.           standard behavior for most C compilers as well.  
  1217.  
  1218.                In C, functions are also considered to be globals - 
  1219.           they are known throughout the program, although they 
  1220.           obviously can't be used to store data.  
  1221.  
  1222.  
  1223.      8.3.2. Local Variables 
  1224.  
  1225.  
  1226.                Variables that are declared inside of the curly braces 
  1227.           that mark the beginning and end of a function are known as 
  1228.           "local" variables.  Locals exist only during the life of the 
  1229.           function - that is the variable comes into existence after 
  1230.           it has been declared within a function and ceases to exist 
  1231.           when the function returns to its caller.  See the example 
  1232.           below for clarification: 
  1233.  
  1234.  
  1235.                char c;             # these are global variables
  1236.                int i;
  1237.                a_function()        # a function definition
  1238.                {
  1239.                     char snafu; # a local variable
  1240.                     int x, y;   # some more locals
  1241.                     .
  1242.                     .
  1243.                     .
  1244.                     x = c;      # copy the global to a local
  1245.                }                   # snafu, x and y cease to exist!
  1246.  
  1247.  
  1248.                                      ____                                             Variable declarations must appear immediately after a 
  1249.           left curly brace; if a declaration appears anywhere else 
  1250.           within the body of a function SCI will warn you about a 
  1251.           "syntax error".  
  1252.  
  1253.                                                              ___                  In addition, variables may be declared within any 
  1254.                                                                  ____             compound statement in a function, but the declarations must 
  1255.           appear immediately after the opening brace.  Variables 
  1256.  
  1257.  
  1258.                                      - 20 -
  1259.  
  1260.  
  1261.      Small C Interpreter                                Programmer's Manual
  1262.  
  1263.  
  1264.           declared in this context exist only for the life of the 
  1265.           compound statement, i.e.  to the matching closing brace.  
  1266.           Thus the memory these variables occupy can be re-used within 
  1267.           the function.  Below is an example to illustrate: 
  1268.  
  1269.  
  1270.                func()
  1271.                {
  1272.                     char a;
  1273.                     int i;
  1274.                     .
  1275.                     .
  1276.                     .
  1277.                     if ( i==0 )
  1278.                     {
  1279.                          int j;      # declare an "int" in a compound stmt
  1280.                          .
  1281.                          .           # "a", "i" and "j" are all locals here
  1282.                          .
  1283.                     }                # "j" no longer exists here
  1284.                     else if ( i==1 )
  1285.                     {
  1286.                          char j;     # a different "j" than above
  1287.                          .
  1288.                          .
  1289.                          .
  1290.                     }
  1291.                }
  1292.  
  1293.  
  1294.                SCI ensures that locals are always zero just after they 
  1295.           have been declared.  On standard C compilers, the initial 
  1296.           contents of locals is unknown, so do not depend on them 
  1297.           being zero.  
  1298.  
  1299.  
  1300.      8.3.3. Function Arguments 
  1301.  
  1302.  
  1303.                Function arguments are also considered to be local 
  1304.           variables.  When a function calls another function and 
  1305.           passes it an argument, the argument's contents is copied 
  1306.           into a local variable in the called function - the value of 
  1307.           the caller's argument is not affected.  This is best 
  1308.           illustrated with an example: 
  1309.  
  1310.  
  1311.                char c;        # the global variable, "c"
  1312.                func1()
  1313.                {
  1314.                     char c;   # a local may have the same name as a global
  1315.                     c = 1;    # and this sets the LOCAL variable "c" to 1!
  1316.  
  1317.  
  1318.                                      - 21 -
  1319.  
  1320.  
  1321.      Small C Interpreter                                Programmer's Manual
  1322.  
  1323.  
  1324.                     func2(c); # now call func2
  1325.                }
  1326.                func2( x )
  1327.                char x;
  1328.                {
  1329.                     char c;   # this "c" is different from func1's "c"
  1330.                     x = 3;    # this does not affect func1's "c"
  1331.                     c = 5;    # this does not affect the global "c"
  1332.                }
  1333.  
  1334.  
  1335.  
  1336.      8.3.4. System Globals 
  1337.  
  1338.  
  1339.                As mentioned earlier, the Library Functions and the 
  1340.           editor's configuration variables that are declared in the 
  1341.           shell are also globals.  These however, are more permanent 
  1342.           than program globals.  A program's global variables can be 
  1343.           zapped into non-existence simply by editing the program and 
  1344.           removing the statement that declares them.  System globals 
  1345.           can not be destroyed since SCI will not allow you to modify 
  1346.           the shell program (or any program for that matter) while it 
  1347.           is still running.  
  1348.  
  1349.  
  1350.      8.4. Location of Variables 
  1351.  
  1352.  
  1353.                At this point it may be useful to discuss where in 
  1354.           memory each of these different types of variables is 
  1355.           located.  Although this depends on the compiler's 
  1356.           implementation and the hardware, most C compilers take 
  1357.           advantage of some commonly used data structures.  
  1358.  
  1359.  
  1360.      8.4.1. The Stack 
  1361.  
  1362.  
  1363.                The stack is simply a chunk of the computer's memory 
  1364.           that can only be accessed (read from and written to) 
  1365.           indirectly through a machine register known as the "stack 
  1366.           pointer".  If the CPU does can not provide a stack pointer 
  1367.           register, the authors of the C compiler will typically write 
  1368.           some subroutines in the machine's language to emulate a 
  1369.           hardware stack.  Reading and writing to the stack proceeds 
  1370.           as follows: before an item is read from the stack, the stack 
  1371.           pointer is decremented to point to the previous item in the 
  1372.           stack memory.  This then, is the item read from the stack; 
  1373.           After an item is written into stack memory, the stack 
  1374.           pointer is incremented to point to the next item in the 
  1375.           stack.  Thus, the operation of the stack can be thought of 
  1376.  
  1377.  
  1378.                                      - 22 -
  1379.  
  1380.  
  1381.      Small C Interpreter                                Programmer's Manual
  1382.  
  1383.  
  1384.           as a stack of pancakes - numbers are piled onto the stack 
  1385.           for temporary storage, then removed from the top as needed.  
  1386.  
  1387.                In general, the C language depends very heavily on the 
  1388.           stack.  Local variables, including function arguments, are 
  1389.           piled onto the stack when a function begins, and then 
  1390.           removed and discarded when it terminates.  As a C statement 
  1391.           is executed, the components of the statement (constants, 
  1392.           variables, etc.) are "pushed" onto the stack until they are 
  1393.           needed.  Then, when the statement is evaluated, the 
  1394.           components are "poped" off the stack.  
  1395.  
  1396.                Most compilers take advantage of the machine's built-in 
  1397.           stack (if the CPU happens to have one, as most do), so 
  1398.           access to the stack is very efficient.  Still, this has 
  1399.           become a major point of criticism by opponents of the C 
  1400.           language.  
  1401.  
  1402.  
  1403.      8.4.2. Program and Data Segments 
  1404.  
  1405.  
  1406.                Global data variables are usually stored in the same 
  1407.           section of memory as program code; most 8 and 16 bit CPU's 
  1408.           do not provide seperate memory segments for program code and 
  1409.           global data.  
  1410.  
  1411.                Some minicomputers and most mainframes do provide 
  1412.           seperate program code and data memory areas.  The machine 
  1413.           then limits access to these segments by disabling the 
  1414.           program from storing data in the code segment and possibly 
  1415.           causing the program to go berserk.  Also, the program is 
  1416.           limited to accessing only its own global data area and 
  1417.           attempts to read or write data outside of this global data 
  1418.           segment is a violation.  
  1419.  
  1420.                Alas, a microcomputer's operating system is at the 
  1421.           mercy of the currently executing program and a careless 
  1422.           program has the ability to corrupt the operating system and 
  1423.           bring the computer to its knees.  
  1424.  
  1425.  
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.  
  1438.                                      - 23 -
  1439.  
  1440.  
  1441.      Small C Interpreter                                Programmer's Manual
  1442.  
  1443.  
  1444.      9. Constants 
  1445.  
  1446.  
  1447.                You already know about decimal integer constants 
  1448.           because we have been using them throughout this tutorial.  
  1449.           The C language also allows you to represent numbers in 
  1450.           hexadecimal, octal and ASCII.  
  1451.  
  1452.  
  1453.      9.1. Hexadecimal Constants 
  1454.  
  1455.  
  1456.                Hexadecimal numbers are distinguished from other number 
  1457.           representations and variables by preceding them with a "0x" 
  1458.           (zero-"ex"), for example: 
  1459.  
  1460.  
  1461.                0x0
  1462.                0x1b
  1463.                0xfa70
  1464.  
  1465.  
  1466.                are all valid hexadecimal number representations.  You 
  1467.           may also use an upper case "x" if you desire.  
  1468.  
  1469.  
  1470.      9.2. Octal Constants 
  1471.  
  1472.  
  1473.                Octal numbers are distinguished by preceding them with 
  1474.           a zero.  These are all valid octal numbers: 
  1475.  
  1476.  
  1477.                00
  1478.                033
  1479.                0175160
  1480.  
  1481.  
  1482.  
  1483.  
  1484.      9.3. ASCII Character Constants 
  1485.  
  1486.  
  1487.                The numeric value of ASCII characters can be 
  1488.           represented by surrounding the ASCII character in 
  1489.           apostrophes, like this: 
  1490.  
  1491.  
  1492.                 A                                                 'A' - is equivalent to decimal 65 
  1493.  
  1494.                ' ' - is a space and is equivalent to decimal 32 
  1495.  
  1496.  
  1497.  
  1498.                                      - 24 -
  1499.  
  1500.  
  1501.      Small C Interpreter                                Programmer's Manual
  1502.  
  1503.  
  1504.                Certain non-printing ASCII characters can also be 
  1505.           conveniently represented as character constants.  By 
  1506.           preceeding certain lower case letters with a backslash 
  1507.           character ("\"), the two-character combination can be used 
  1508.           to represent a single one byte value.  One of these you 
  1509.           already know as the "newline" character, '\n'. Here is a 
  1510.           complete list of these: 
  1511.  
  1512.  
  1513.                  b                                                            '\b' - "backspace", equivalent to decimal 8.  
  1514.  
  1515.                  r                                                  '\r' - "return", equivalent to 13.  
  1516.  
  1517.                  n                                                   '\n' - "newline", equivalent to 10.  
  1518.  
  1519.                  f                                                    '\f' - "formfeed", equivalent to 12.  
  1520.  
  1521.                  t                                              '\t' - "tab", equivalent to 9.  
  1522.  
  1523.  
  1524.                In addition, you can represent any ASCII character as a 
  1525.           character constant using its octal equivalent preceded by a 
  1526.           backslash.  The only restriction here is that the octal 
  1527.           representation must be exactly 3 octal digits.  For example: 
  1528.  
  1529.  
  1530.                  033                                                                  '\033' - is an ASCII "escape" character equivalent to 
  1531.                     27.  
  1532.  
  1533.                  101                                                                    '\101' - is an ASCII "A", equivalent to 'A', equivalent 
  1534.                     to 65.  
  1535.  
  1536.                  377                                                                   '\377' - is not really a valid ASCII character, but it 
  1537.                     is equivalent to 255.  
  1538.  
  1539.           
  1540.           and so on - you get the idea.  
  1541.  
  1542.  
  1543.      9.4. String Constants 
  1544.  
  1545.  
  1546.                Finally, another type of constant you have already been 
  1547.           using, is the "string" constant - a bunch of ASCII 
  1548.           characters surrounded by quotes, for example: 
  1549.  
  1550.  
  1551.                "this is a string\n"
  1552.  
  1553.  
  1554.                A string always ends with a zero byte, thus the amount 
  1555.           of memory a string takes up is equal to the number of 
  1556.  
  1557.  
  1558.                                      - 25 -
  1559.  
  1560.  
  1561.      Small C Interpreter                                Programmer's Manual
  1562.  
  1563.  
  1564.           characters you can count in the string plus one.  In the 
  1565.           example above, the string requires 18 bytes of storage 
  1566.           (realize that the "\n" sequence is a single character - the 
  1567.           "newline"!).  
  1568.  
  1569.                String constants have an interesting numeric equivalent 
  1570.           - it is an address in the computer's memory where the ASCII 
  1571.           characters in the string can be found by functions that are 
  1572.           equiped to deal with them.  For instance, the Library 
  1573.           Function "puts" expects its parameter to be an address in 
  1574.           memory where ASCII character can be found and sequentially 
  1575.           printed out to the console screen.  
  1576.  
  1577.                If you tried to find out a string constant's numeric 
  1578.           value from the shell by typing: 
  1579.  
  1580.  
  1581.                > "hello?"
  1582.                -5537
  1583.                > "another string..."
  1584.                -5537
  1585.                > "what the?"
  1586.                -5537
  1587.                >
  1588.  
  1589.  
  1590.                you would be surprised to find that they all have the 
  1591.           same address - how could this be?  Actually, all the string 
  1592.           constants in the above examples do have the same address.  
  1593.           Recall that the shell reads a line of input from the console 
  1594.           and hands it off to the interpreter for evaluation.  Since 
  1595.           the strings all get read into the same line buffer by the 
  1596.           shell, they all have the same address, namely the shell's 
  1597.           input line buffer.  
  1598.  
  1599.                We will discuss strings in more detail in the section 
  1600.           on arrays and pointers.  
  1601.  
  1602.  
  1603.  
  1604.  
  1605.  
  1606.  
  1607.  
  1608.  
  1609.  
  1610.  
  1611.  
  1612.  
  1613.  
  1614.  
  1615.  
  1616.  
  1617.  
  1618.                                      - 26 -
  1619.  
  1620.  
  1621.      Small C Interpreter                                Programmer's Manual
  1622.  
  1623.  
  1624.      10. Assignment Operator 
  1625.  
  1626.  
  1627.                In C, we assign values to variables using the 
  1628.           "assignment" operator, "=".  Do not confuse the assignment 
  1629.           operator (a single equal sign) with the "is equal to" 
  1630.           relational operator (two consecutive equal signs), which we 
  1631.           will discuss later.  Although C will allow you to do this 
  1632.           under certain conditions, you will get unexpected results.  
  1633.           The expression: 
  1634.  
  1635.  
  1636.                a = (b + 1) * 2;
  1637.  
  1638.           is read as: take the results of the calculation of (b + 1) * 
  1639.           2 and assign it to the variable "a". Note that there may be 
  1640.           only one variable to the left of the equal sign.  
  1641.  
  1642.                You can if you like, string several of these 
  1643.           assignments together like this: 
  1644.  
  1645.  
  1646.                a = flg = x = (b + 1) * 2;
  1647.  
  1648.  
  1649.                Note that even here there is always only one variable 
  1650.           to the left of each equal sign.  This statement is evaluated 
  1651.           like so: take the results of the calculation of (b + 1) * 2 
  1652.           and assign it to the variable "x", then assign the same 
  1653.           number to the variable "flg", and then to "a".  This implies 
  1654.           that the assignment operator is evaluated from 
  1655.           _____ __ ____                                                           right-to-left, instead of the usual left-to-right.  In fact 
  1656.           it is the only binary operator supported by SCI that 
  1657.           exhibits this peculiar behavior.  This feature is most 
  1658.           useful when initializing several variables, like so: 
  1659.  
  1660.  
  1661.                lettercnt = digitcnt = punctcnt = 0;
  1662.  
  1663.           
  1664.           which would set all of the variables to zero.  
  1665.  
  1666.                The assignment operator has the lowest precedence (it 
  1667.           is performed last in an expression) of all the C operators, 
  1668.           except for the "comma" operator (see below).  
  1669.  
  1670.  
  1671.      10.1. Lvalues and Rvalues 
  1672.  
  1673.  
  1674.                It should be intuitively obvious that any attempt to 
  1675.           store a value in what we know as a C constant is illegal.  
  1676.  
  1677.  
  1678.                                      - 27 -
  1679.  
  1680.  
  1681.      Small C Interpreter                                Programmer's Manual
  1682.  
  1683.  
  1684.           In other words, you would never attempt to say, store the 
  1685.           number 3 in place of the number 5: 
  1686.  
  1687.  
  1688.                5 = 3;
  1689.  
  1690.  
  1691.                The same holds true for string constants; you may not 
  1692.           store another string in an existing string constant: 
  1693.  
  1694.  
  1695.                "hello" = "world\n";
  1696.  
  1697.  
  1698.                These types of data (constants) are collectively known 
  1699.           as "rvalues" (pronounced "are-values"). The term rvalue 
  1700.           stems from the fact that they may only be used on the 
  1701.           right-hand-side of an assignment operator.  
  1702.  
  1703.                On the other hand, variables do allow numbers to be 
  1704.           stored and retrieved from them.  This category of data is 
  1705.           known as "lvalues" (pronounced "ell-values") because they 
  1706.           may be used on the left-hand-side of an eual sign.  
  1707.  
  1708.                We will encounter lvalues and rvalues again in a later 
  1709.           discussion.  
  1710.  
  1711.  
  1712.  
  1713.  
  1714.  
  1715.  
  1716.  
  1717.  
  1718.  
  1719.  
  1720.  
  1721.  
  1722.  
  1723.  
  1724.  
  1725.  
  1726.  
  1727.  
  1728.  
  1729.  
  1730.  
  1731.  
  1732.  
  1733.  
  1734.  
  1735.  
  1736.  
  1737.  
  1738.                                      - 28 -
  1739.  
  1740.  
  1741.      Small C Interpreter                                Programmer's Manual
  1742.  
  1743.  
  1744.      11. Comma Operator 
  1745.  
  1746.  
  1747.                In C the punctuation character "," (comma) is 
  1748.           considered to be an operator, although it does nothing more 
  1749.           except insure that sub-expressions within a statement will 
  1750.           be evaluated in order from left to right.  This operator has 
  1751.           the lowest priority of all.  It is useful for when you want 
  1752.           to do more than one thing in a statement, like the 
  1753.           following: 
  1754.  
  1755.  
  1756.                ++a, b=12, c=b+a;
  1757.  
  1758.  
  1759.                Of course, we could also have written the above 
  1760.           statement as: 
  1761.  
  1762.  
  1763.                {
  1764.                     ++a;
  1765.                     b=12;
  1766.                     c=b+a;
  1767.                }
  1768.  
  1769.           
  1770.           but this would not have been as concise as the first form.  
  1771.  
  1772.                Commas are also used to seperate variable names in a 
  1773.           data declaration as you have already seen, and to seperate 
  1774.           arguments in function calls.  
  1775.  
  1776.  
  1777.                                      NOTE                                        NOTE:
  1778.  
  1779.                SCI does not support the use of the comma operator 
  1780.                anywhere   outside   the   context   of   variable
  1781.                seperators or function call  argument  seperators,
  1782.                as in  the first example above.  Any attempt to do
  1783.                so will result in a "syntax  error"  message  from
  1784.                the interpreter.  
  1785.  
  1786.  
  1787.  
  1788.  
  1789.  
  1790.  
  1791.  
  1792.  
  1793.  
  1794.  
  1795.  
  1796.  
  1797.  
  1798.                                      - 29 -
  1799.  
  1800.  
  1801.      Small C Interpreter                                Programmer's Manual
  1802.  
  1803.  
  1804.      12. Flow Control 
  1805.  
  1806.  
  1807.                The previous sections have dealt only with data 
  1808.           elements (variables and constants) and with evaluating 
  1809.           arithmetic combinations of these.  C would be a poor 
  1810.           language indeed if it only allowed a programmer to evaluate 
  1811.           a sequential list of arithmetic expressions without giving 
  1812.           him the opportunity to act on the results of these 
  1813.           calculations.  This section will introduce you to C's 
  1814.           program control structures, also known as "flow control" 
  1815.           structures.  Most of these have constructs that should be 
  1816.           familiar to all you BASIC hackers: the conditional 
  1817.           ("if-else"), looping ("while" and "for") and program control 
  1818.           switching ("switch").  
  1819.  
  1820.  
  1821.      12.1. if and if-else 
  1822.  
  1823.  
  1824.                The most fundamental of the flow control constructs is 
  1825.           the "if".  This allows you to perform a statement (or group 
  1826.           of statements if we talk about a compound statement) "if" 
  1827.           the given condition is true.  In C, a condition is 
  1828.           considered to be true when the value of an expression is 
  1829.           non-zero, that is either a positive or negative number.  It 
  1830.           follows then, that an expression that evaluates to zero is 
  1831.           considered to be a false condition.  We write an "if" 
  1832.           conditional in C like this: 
  1833.  
  1834.  
  1835.                if ( <expression> ) <statement>
  1836.  
  1837.  
  1838.                We will be using the angle brackets (<>) to represent 
  1839.           familiar C concepts so that you will be able to more easily 
  1840.           identify the relavent components: here "<expression>" is any 
  1841.           valid C expression, like "var-5" or "x + 10"; and 
  1842.           "<statement>" may be either a simple or compound statement - 
  1843.           but, more about statements later.  
  1844.  
  1845.                The relavent components in the "if" statement are: 
  1846.           obviously the "if" word which identifies this flow control 
  1847.           construct; a left parenthesis followed by an expression 
  1848.           followed by a right parenthesis; then a C statement.  Now a 
  1849.           few words about syntactics: 
  1850.  
  1851.  
  1852.                1) The "if" must be in lower case letters, most C 
  1853.                     compilers will usually not accept "If", or "IF" or 
  1854.                     "iF" (and neither will SCI!).  
  1855.  
  1856.  
  1857.  
  1858.                                      - 30 -
  1859.  
  1860.  
  1861.      Small C Interpreter                                Programmer's Manual
  1862.  
  1863.  
  1864.                2) The matched left and right parentheses must be 
  1865.                     included, and SCI requires that the "if", the left 
  1866.                     parenthesis, the <expression> and the right 
  1867.                     parenthesis appear on the same line in the 
  1868.                     program.  
  1869.  
  1870.                3) The <statement> may be either a simple statement or 
  1871.                     a compound statement.  
  1872.  
  1873.  
  1874.  
  1875.                                      NOTE                                        NOTE:
  1876.  
  1877.                SCI  requires  that  the  "if" and the parentheses
  1878.                appear on the same line in your program text,  but
  1879.                the  <statement> may appear on the following line.
  1880.                This is only a restriction of the SCI  interpreter
  1881.                -  the  standard  C  language lets you put as much
  1882.                horizontal   and   vertical   "distance"   between
  1883.                elements of an "if" statement as you like.  
  1884.  
  1885.           
  1886.           The "if" flow control construct behaves as follows: 
  1887.  
  1888.  
  1889.                1) The <expression> is evaluated.  
  1890.  
  1891.                2) If the result of <expression> is true (a non-zero 
  1892.                     value) then the <statement> is executed.  
  1893.  
  1894.                3) If the result is false (zero) the <statement> is 
  1895.                     skipped and program control passes to the next 
  1896.                     statement.  
  1897.  
  1898.           
  1899.           For example: 
  1900.  
  1901.  
  1902.                if ( 2 + 2 ) a = 5;
  1903.  
  1904.           
  1905.           would always set the variable "a" to 5 because the 
  1906.           <expression>, which evaluates to 4 in this case, is always 
  1907.           non-zero.  And the <statement> in this example: 
  1908.  
  1909.  
  1910.                if ( 0 ) a = 5;
  1911.  
  1912.           
  1913.           would never be reached because the <expression> is always 
  1914.           false.  As a last example, look at this: 
  1915.  
  1916.  
  1917.  
  1918.                                      - 31 -
  1919.  
  1920.  
  1921.      Small C Interpreter                                Programmer's Manual
  1922.  
  1923.  
  1924.                if ( a = b + c ) b = b + 1;
  1925.  
  1926.  
  1927.                Here the value of the <expression> depends on the 
  1928.           results of the addition of "b" and "c", which we have no way 
  1929.           of knowing just by looking at the example out of context.  
  1930.           As a side-effect, the result of the addition is stored in 
  1931.           the variable "a". It is very important that you realize that 
  1932.           the equal sign in "a = b + c" is not making a comparison 
  1933.           between the value of "a" and "b + c", as you might assume if 
  1934.           you were looking at a similar statement in BASIC.  In other 
  1935.                         ___                                                       words, we are not saying "if a is equal to the sum of b and 
  1936.           c".  
  1937.  
  1938.  
  1939.      12.1.1. More About Statements 
  1940.  
  1941.  
  1942.                Earlier we promised to tell you more about the concept 
  1943.           of C statements.  A statement, as you already know, can be 
  1944.           either an expression such as "a = 5 + 5" followed by a 
  1945.           semicolon (don't forget the semicolon!) or it may be a group 
  1946.           of these simple statements surrounded by left and right 
  1947.           curly braces, like this: 
  1948.  
  1949.  
  1950.                { a = b + c; b = b + 1; }
  1951.  
  1952.           
  1953.           or this: 
  1954.  
  1955.  
  1956.                {
  1957.                     a = b + c;
  1958.                     b = b + 1;
  1959.                }
  1960.  
  1961.           
  1962.           or a compound statement within a compound statement as in 
  1963.           this example: 
  1964.  
  1965.  
  1966.                {
  1967.                     { a = b; b = 1; }
  1968.                     a = b + c;
  1969.                     b = b + 1;
  1970.                }
  1971.  
  1972.  
  1973.                We now expand our definition of a C statement to 
  1974.           include the "if" and later all of the other flow control 
  1975.           constructs as well.  In other words, the template for an 
  1976.  
  1977.  
  1978.                                      - 32 -
  1979.  
  1980.  
  1981.      Small C Interpreter                                Programmer's Manual
  1982.  
  1983.  
  1984.           "if" we showed you before: 
  1985.  
  1986.  
  1987.                if ( <expression> ) <statment>
  1988.  
  1989.           
  1990.           can be thought of as a single unit and used wherever a 
  1991.           <statement> is used.  Now we can write multiple "nested 
  1992.           if's" like this: 
  1993.  
  1994.  
  1995.                if ( a + 5 )
  1996.                     if ( b - 1 )
  1997.                          c = 0;
  1998.  
  1999.           
  2000.           which would be "read" by the computer as follows: 
  2001.  
  2002.  
  2003.                1) if "a + 5" is true (non-zero) then go to step 2 
  2004.                     otherwise go to step 3.  
  2005.  
  2006.                2) if "b - 1" is true, then assign 0 to "c".  
  2007.  
  2008.                3) go on to the next statement in the program.  
  2009.  
  2010.  
  2011.                The "if" statement also has an optional "else" clause, 
  2012.           which looks like this: 
  2013.  
  2014.  
  2015.                if ( <expression> ) <statement> else <statement>
  2016.  
  2017.  
  2018.                Notice that the "else" keyword must be in lower case 
  2019.           letters also.  Again, the first <statement>, the "else", and 
  2020.           the second <statement> may be on seperate lines of program 
  2021.           text or they may all be on the same line.  The "if-else" 
  2022.           statement, as it is called, is read as follows: 
  2023.  
  2024.  
  2025.                1) if the <expression> is true, then execute the first 
  2026.                     <statement> and then go to step 3.  
  2027.  
  2028.                2) else, execute the second <statement> and then go to 
  2029.                     step 3.  
  2030.  
  2031.                3) go on to the next statement in the program.  
  2032.  
  2033.  
  2034.                The C language allows you to nest "if-else" statements 
  2035.           as deeply as you wish, for example: 
  2036.  
  2037.  
  2038.                                      - 33 -
  2039.  
  2040.  
  2041.      Small C Interpreter                                Programmer's Manual
  2042.  
  2043.  
  2044.                if ( a + 3 )
  2045.                     if ( b + 5 )
  2046.                          if ( c + 7 )
  2047.                               d = 0;
  2048.                          else
  2049.                               d = 1;
  2050.                     else
  2051.                          d = 2;
  2052.                else
  2053.                     d = 3;
  2054.  
  2055.  
  2056.                It should be obvious from the way the statements were 
  2057.           indented how each "else" matches its "if". As a matter of 
  2058.           definition, an "else" clause matches the nearest preceding 
  2059.           "if" clause.  If there are more "else's" than "if's" in a 
  2060.           program, then this is an error condition and you will be 
  2061.           warned by SCI. If you are ever unsure how nested "if-else" 
  2062.           combinations will match up, you can always use curly braces 
  2063.           to bind them together the way you want: 
  2064.  
  2065.  
  2066.                if ( a + 3 )
  2067.                {
  2068.                     if ( b + 5 )
  2069.                     {
  2070.                          if ( c + 7 )
  2071.                               d = 0;
  2072.                          else
  2073.                               d = 1;
  2074.                     }
  2075.                     else
  2076.                     {
  2077.                          d = 2;
  2078.                     }
  2079.                }
  2080.                else
  2081.                {
  2082.                     d = 3;
  2083.                }
  2084.  
  2085.  
  2086.                You can also use another "if-else" statement in the 
  2087.           "else" clause of a preceding "if-else", for example: 
  2088.  
  2089.  
  2090.  
  2091.  
  2092.  
  2093.  
  2094.  
  2095.  
  2096.  
  2097.  
  2098.                                      - 34 -
  2099.  
  2100.  
  2101.      Small C Interpreter                                Programmer's Manual
  2102.  
  2103.  
  2104.                if ( a + 3 )
  2105.                     d = 1;
  2106.                else
  2107.                {
  2108.                     if ( a + 4 )
  2109.                          d = 2;
  2110.                     else
  2111.                     {
  2112.                          if ( a + 5 )
  2113.                               d = 3;
  2114.                          else
  2115.                               d = 4;
  2116.                     }
  2117.                }
  2118.  
  2119.  
  2120.                Because it is a matter of personal style, there are no 
  2121.           hard and fast rules to follow when indenting program 
  2122.           statements like this.  However, the above example is more 
  2123.           commonly indented like this: 
  2124.  
  2125.  
  2126.                if ( a + 3 )
  2127.                     d = 1;
  2128.                else if ( a + 4 )
  2129.                     d = 2;
  2130.                else if ( a + 5 )
  2131.                     d = 3;
  2132.                else
  2133.                     d = 4;
  2134.  
  2135.  
  2136.                This saves you from running off the right edge of the 
  2137.           screen when writing very deeply nested "if-else's" and it 
  2138.           looks very much like a multi-path switch (an "ON GOTO" 
  2139.           statement in BASIC).  
  2140.  
  2141.  
  2142.      12.1.2. Relational Operators 
  2143.  
  2144.  
  2145.                Sometimes it is necessary to change the program flow 
  2146.           depending on whether a variable is equal to a certain 
  2147.           value.  The C language has this ability to test equality of 
  2148.           two expressions using a set of operators (similar to the 
  2149.           addition, multiplication, assignment, etc.) known as the 
  2150.           "relational operators".  If we wanted to know if a variable 
  2151.           were equal to a certain value, for instance we could say: 
  2152.  
  2153.  
  2154.                a == 5
  2155.  
  2156.  
  2157.  
  2158.                                      - 35 -
  2159.  
  2160.  
  2161.      Small C Interpreter                                Programmer's Manual
  2162.  
  2163.  
  2164.                The "==" (which is read as: "is equal to") operator 
  2165.           compares the two items to the left and right of it and 
  2166.           leaves a value of one if they are equal, zero if they are 
  2167.           unequal.  So the value of this expression would be one if 
  2168.           "a" is equal to 5 and zero otherwise.  Thus, the statement: 
  2169.  
  2170.  
  2171.                if ( a == 5 )
  2172.                     b = 0;
  2173.  
  2174.           
  2175.           would set "b" to zero only if "a" equals 5.  
  2176.  
  2177.                We promised you a set of these operators, so here they 
  2178.           are: 
  2179.  
  2180.  
  2181.                ________    ____ __                  operator:   read as:
  2182.                
  2183.                ==          is equal to
  2184.                !=          is not equal to
  2185.                <           is less than
  2186.                >           is greater than
  2187.                <=          is less than or equal to
  2188.                >=          is greater than or equal to
  2189.  
  2190.  
  2191.                Notice that there may be no spaces between the two 
  2192.           equal signs (=) in the "is equal to" operator nor between 
  2193.           the exclamation point (!) and the equal in the "is not equal 
  2194.           to".  If there is a space between them, they will be assumed 
  2195.           to be two seperate operators and you will get a "syntax 
  2196.           error" message from SCI. Needless to say, the same goes for 
  2197.           the <= and >=.  
  2198.  
  2199.  
  2200.      12.1.3. Logical Operators 
  2201.  
  2202.  
  2203.                The C language also allows you to combine groups of 
  2204.           relational expressions with "and" and "or" clauses.  For 
  2205.           example, given two sets of conditions you can determine if 
  2206.           both are true, or if at least one is true.  These "and" and 
  2207.           "or" clauses are known as the "logical operators" in C: 
  2208.  
  2209.  
  2210.                ________    ____ __                  operator:   read as:
  2211.                
  2212.                &&          and
  2213.                ||          or
  2214.  
  2215.  
  2216.  
  2217.  
  2218.                                      - 36 -
  2219.  
  2220.  
  2221.      Small C Interpreter                                Programmer's Manual
  2222.  
  2223.  
  2224.                Notice that there may be no spaces between the two 
  2225.           ampersands (&) and vertical bars (|). The expression: 
  2226.  
  2227.  
  2228.                a==5 && b==3
  2229.  
  2230.           
  2231.                                                  ___                             will be true only if "a" is equal to 5 and "b" is equal to 
  2232.           3.  
  2233.  
  2234.  
  2235.                a<0 || 10<a
  2236.  
  2237.  
  2238.                In this example the expression is true if "a" is less 
  2239.                  __                                                                than 0 or greater than 10 (do you see that 10<a and a>10 are 
  2240.           identical?).  
  2241.  
  2242.                One final note about the logical operators: standard C 
  2243.           stops evaluating an expression that contains logical 
  2244.           operators after the truth or falsehood of the expression is 
  2245.           known.  For example: 
  2246.  
  2247.  
  2248.                a==b && c==d
  2249.  
  2250.  
  2251.                Assume that "a" is not equal to "b". Standard C would 
  2252.           not even bother checking the relation "c==d" because the 
  2253.           "and" clause requires both expressions to the left and right 
  2254.           of the "&&" to be true - if one of the components is false, 
  2255.           the entire expression is false.  So, since the first 
  2256.           component encountered ("a==b") was found to be false, the 
  2257.           truth or falsehood of the entire expression is already known 
  2258.           and there is no need to evaluate "c==d".  
  2259.  
  2260.  
  2261.                                      NOTE                                        NOTE:
  2262.  
  2263.                SCI  is  not as smart as a standard C compiler and
  2264.                blindly  evaluates  every  sub-expression   in   a
  2265.                logical expression.    This  can lead to some very
  2266.                hard to find errors if for  example  you  alter  a
  2267.                variable in one of the subexpressions of a logical 
  2268.                operation - sorry folks!  
  2269.  
  2270.  
  2271.  
  2272.      12.1.4. Precedence and Associativity 
  2273.  
  2274.  
  2275.                You can combine as many "and" and "or" clauses as 
  2276.  
  2277.  
  2278.                                      - 37 -
  2279.  
  2280.  
  2281.      Small C Interpreter                                Programmer's Manual
  2282.  
  2283.  
  2284.           necessary: 
  2285.  
  2286.  
  2287.                a==5 || b==3 && c==4
  2288.  
  2289.  
  2290.                This expression will be true under one of two 
  2291.           conditions: 1) b is equal to 3 AND c is equal to 4, or 2) a 
  2292.           is equal to 5. This example shows a very important property 
  2293.           of logical operators that we have already encountered in the 
  2294.           discussion of the arithmetic operators (+, -, *, etc.), 
  2295.           namely precedence.  In C, the && operator takes precedence 
  2296.           (is performed before) the || operator.  
  2297.  
  2298.                As with the arithmetic operators the logical operators 
  2299.           are performed from left to right.  So, if we have more than 
  2300.           one operator of the same precedence in an expression: 
  2301.  
  2302.  
  2303.                a==5 && b==5 && c==5
  2304.  
  2305.           
  2306.           we know that C performs the tests for equality from left to 
  2307.           right.  
  2308.  
  2309.                Although we haven't come right out and said it before, 
  2310.           it should be obvious from the examples that the relational 
  2311.           operators have higher precedence than the logical 
  2312.           operators.  Specifically, >, >=, < and <= have higher 
  2313.           precedence than == and != which have higher precedence than 
  2314.           && which has a higher precedence than ||.  Please refer to 
  2315.           the Language Summary section of the User's Manual for a 
  2316.           complete list of C operators and their order of precedence.  
  2317.  
  2318.                Furthermore, relational operators associate from left 
  2319.           to right, although it is hardly ever necessary to use more 
  2320.           than one consecutive relational: 
  2321.  
  2322.  
  2323.                a == 5 != 1
  2324.  
  2325.  
  2326.                Notice in this example that "a == 5" is performed first 
  2327.           which would result in either a zero or a one.  Examine the 
  2328.           following expression closely: 
  2329.  
  2330.  
  2331.                a < 5 == b < 5
  2332.  
  2333.  
  2334.                                                               ____                  This expresion will be true if "a" and "b" are both 
  2335.           ____ ____ _                    ____ _____ __ __ _______ ____             less than 5 or "a" and "b" are both equal to or greater than 
  2336.  
  2337.  
  2338.                                      - 38 -
  2339.  
  2340.  
  2341.      Small C Interpreter                                Programmer's Manual
  2342.  
  2343.  
  2344.           _               5.  
  2345.  
  2346.                As always, whenever you are in doubt about the 
  2347.           associativity or precedence of operators, either use 
  2348.           parentheses to bind operands and operators together, or 
  2349.           consult the table of operators in the User's Manual.  
  2350.  
  2351.  
  2352.      12.1.5. Examples 
  2353.  
  2354.  
  2355.                Finally armed with these new facts about C, we are 
  2356.           ready to try some practical examples using the SCI 
  2357.           interpreter.  Enter the following program using the SCI 
  2358.           editor: 
  2359.  
  2360.  
  2361.                convert(n)
  2362.                {
  2363.                     char c;
  2364.                
  2365.                     puts("to decimal (d), hex (x) or octal (o) ?");
  2366.                     c=getchar();
  2367.                     if(c=='d')
  2368.                          putd(n);
  2369.                     else if(c=='x')
  2370.                          putx(n);
  2371.                     else if(c=='o')
  2372.                          puto(n);
  2373.                     else
  2374.                          puts("what?\n");
  2375.                }
  2376.  
  2377.  
  2378.                As you can probably tell, this is a number conversion 
  2379.           routine.  It asks the operator whether to convert the number 
  2380.           passed to it ("n") to decimal, hexadecimal or octal.  Now at 
  2381.           the shell prompt, type: 
  2382.  
  2383.  
  2384.                > convert( 255 )
  2385.                to decimal (d), hex (x) or octal (o) ?x
  2386.                0xff
  2387.                0
  2388.                >
  2389.  
  2390.  
  2391.                If your screen did not look like the above, there is 
  2392.           something wrong - fix it up and try again.  
  2393.  
  2394.                Now modify the program to accept either lower or upper 
  2395.           case d's, x's and o's (hint: use the || operator).  
  2396.  
  2397.  
  2398.                                      - 39 -
  2399.  
  2400.  
  2401.      Small C Interpreter                                Programmer's Manual
  2402.  
  2403.  
  2404.      12.2. while 
  2405.  
  2406.  
  2407.                One of the things that makes a computer such a powerful 
  2408.           tool is its tireless ability to perform repetitive tasks.  
  2409.           This is why every programming language has some sort of 
  2410.           "looping" flow control.  The C language offers three types 
  2411.           of loop constucts: the "while", "for" and "do-while".  This 
  2412.           version of SCI only supports the "while" and "for".  
  2413.  
  2414.                The "while" flow control looks something like this: 
  2415.  
  2416.  
  2417.                while ( <expression> ) <statement>
  2418.  
  2419.  
  2420.                Notice that its structure is very similar to the "if" 
  2421.           construct and all of the syntactical rules apply as well.  
  2422.           This statement is executed as follows: 
  2423.  
  2424.  
  2425.                1) evaluate <expression> and if it is false, go to step 
  2426.                     4.  
  2427.  
  2428.                2) execute <statement>.  
  2429.  
  2430.                3) go to step 1 
  2431.  
  2432.                4) go on to the next statement in the program.  
  2433.  
  2434.  
  2435.                As with the "if" statement, <expression> is considered 
  2436.           to be true if it evaluates to non-zero, and false if it is 
  2437.           zero.  Let's look at an example: 
  2438.  
  2439.  
  2440.                loop()
  2441.                {
  2442.                     int a;
  2443.                
  2444.                     a = 10;
  2445.                     while ( a > 0 )
  2446.                     {
  2447.                          putd( a );
  2448.                          a = a - 1;
  2449.                     }
  2450.                     puts("all done\n");
  2451.                }
  2452.  
  2453.  
  2454.                This loop will get executed exactly 10 times - each 
  2455.           time the variable "a" is decremented by one until it equals 
  2456.  
  2457.  
  2458.                                      - 40 -
  2459.  
  2460.  
  2461.      Small C Interpreter                                Programmer's Manual
  2462.  
  2463.  
  2464.           zero.  When "a" reaches zero, the expression "a > 0" will 
  2465.           become false and program execution will continue with the 
  2466.           next statement in the program.  
  2467.  
  2468.                There is also a more direct method of breaking out of a 
  2469.           "while" loop without having to wait until control returns 
  2470.           back to the <expression> evaluation and testing.  Using a 
  2471.           "break" statement, you can directly jump out of a "while" 
  2472.           and continue with the next statement in the program.  The 
  2473.           following demonstrates the use of a "break": 
  2474.  
  2475.  
  2476.                loop()
  2477.                {
  2478.                     int i, r;
  2479.                
  2480.                     i = 13560;
  2481.                     putd( i );
  2482.                     while ( 1 )
  2483.                     {
  2484.                          r = i / 10;
  2485.                          if ( r == 0 )
  2486.                               break;
  2487.                          putd( r );
  2488.                          i = r;
  2489.                     }
  2490.                     puts("all done\n");
  2491.                }
  2492.  
  2493.  
  2494.                Since the <expression> is always true (1 is always 
  2495.           non-zero), this loop would be repeated until the cows came 
  2496.           home.  The "if" statement within the loop will break out of 
  2497.           the loop when the remainder of the division results in 
  2498.           zero.  We leave as an exercise for the student to figure out 
  2499.           what this little program does.  
  2500.  
  2501.  
  2502.      12.3. for 
  2503.  
  2504.  
  2505.                The "for" looping construct is similar to the "while". 
  2506.           Its format is as follows: 
  2507.  
  2508.  
  2509.                for ( <expression> ; <expression> ; <expression> ) <statement>
  2510.  
  2511.  
  2512.                The syntactical requirements of the "for" construct are 
  2513.           similiar to those of the "while" - the "for" and the 
  2514.           parentheses and everything between them must be on the same 
  2515.           program line.  Also, the three <expression>'s inside the 
  2516.  
  2517.  
  2518.                                      - 41 -
  2519.  
  2520.  
  2521.      Small C Interpreter                                Programmer's Manual
  2522.  
  2523.  
  2524.           parentheses must be seperated from each other by two 
  2525.           semicolons as shown.  
  2526.  
  2527.                Actually, the "for" is simply a method of clearly 
  2528.           presenting to the reader the most commonly needed elements 
  2529.           relavent to a program loop: an "initialization" part, a 
  2530.           "loop test" part and an "iteration" part.  These three 
  2531.           elements are clearly identifyable, and correspond to 
  2532.           (reading from left to right) the three <expressions> within 
  2533.           the parentheses.  
  2534.  
  2535.                A "for" statement would be executed as follows: 
  2536.  
  2537.  
  2538.                1) evaluate the first <expression>, disregard the 
  2539.                     result.  
  2540.  
  2541.                2) evaluate the second <expression> and if it is false, 
  2542.                     go to step 5.  
  2543.  
  2544.                3) execute <statement>.  
  2545.  
  2546.                4) evaluate the third <expression> and go to step 2.  
  2547.  
  2548.                5) go on to the next statement in the program.  
  2549.  
  2550.  
  2551.                We could have written the first example given for the 
  2552.           "while" using a "for" statement: 
  2553.  
  2554.  
  2555.                loop()
  2556.                {
  2557.                     int a;
  2558.                
  2559.                     for ( a = 10; a > 0; a = a - 1 )
  2560.                          putd( a );
  2561.                }
  2562.  
  2563.  
  2564.                The "break" statement may also be used to break out of 
  2565.           a "for" loop.  One last interesting feature of the "for" is 
  2566.           that any or all of the three <expressions> may be missing.  
  2567.           If the second <expression> is missing, the "loop test" will 
  2568.           always evaluate to true.  Thus, the second example of the 
  2569.           "while" loop above could have been written: 
  2570.  
  2571.  
  2572.  
  2573.  
  2574.  
  2575.  
  2576.  
  2577.  
  2578.                                      - 42 -
  2579.  
  2580.  
  2581.      Small C Interpreter                                Programmer's Manual
  2582.  
  2583.  
  2584.                loop()
  2585.                {
  2586.                     int i, r;
  2587.                
  2588.                     for ( putd( i = 13560 ); ; i = r )
  2589.                     {
  2590.                          r = i / 10;
  2591.                          if ( r == 0 )
  2592.                               break;
  2593.                          putd( r );
  2594.                     }
  2595.                }
  2596.  
  2597.  
  2598.                Here, the three <expressions> are: 
  2599.  
  2600.  
  2601.                putd( i = 12560 )
  2602.                
  2603.                missing!
  2604.                
  2605.                i = r
  2606.  
  2607.  
  2608.                And the most efficient way of writing a "forever" loop 
  2609.           is: 
  2610.  
  2611.  
  2612.                for ( ;; )
  2613.                     puts( "hello, world\n" );
  2614.  
  2615.           
  2616.  
  2617.  
  2618.      12.4. switch 
  2619.  
  2620.  
  2621.                The last and most complex flow control we will examine 
  2622.           is the multi-path "switch" statement.  The "switch" is 
  2623.           similar to BASIC's "ON GOTO" statement.  Here is the 
  2624.           template of a "switch" statement: 
  2625.  
  2626.  
  2627.  
  2628.  
  2629.  
  2630.  
  2631.  
  2632.  
  2633.  
  2634.  
  2635.  
  2636.  
  2637.  
  2638.                                      - 43 -
  2639.  
  2640.  
  2641.      Small C Interpreter                                Programmer's Manual
  2642.  
  2643.  
  2644.                switch ( <expression> )
  2645.                {
  2646.                case <constant expression> : <statement>
  2647.                case <constant expression> : <statement>
  2648.                     .
  2649.                     .
  2650.                     .
  2651.                case <constant expression> : <statement>
  2652.                default : <statement>
  2653.                }
  2654.  
  2655.  
  2656.                Again, the word "switch", the left parenthesis, the 
  2657.           <expression> and the right parenthesis must be on the same 
  2658.           program source line.  The matching left and right curly 
  2659.           brace at the beginning and end of the switch are not 
  2660.           actually required but are necessary as you will soon see.  
  2661.           The words "case" and "default" are only meaningful within 
  2662.           the context of a "switch" statement.  There may be any 
  2663.           number of "case <constant expression> :" sequences but only 
  2664.           one "default :".  The <constant expression>'s are simply 
  2665.           <expression>'s that contain only constants (no variables!).  
  2666.           So, the following would all be examples of <constant 
  2667.           expression>'s: 
  2668.  
  2669.  
  2670.                2 + 2
  2671.                25 * (365 / 7)
  2672.                37/12 > 10
  2673.  
  2674.  
  2675.  
  2676.                                      NOTE                                        NOTE:
  2677.  
  2678.                Standard    C   requires   that   only   <constant
  2679.                expression>'s follow a "case", however SCI  allows
  2680.                you  to  use  any  valid  <expression> as an added
  2681.                bonus.   Keep  this  fact  in  mind  when  writing
  2682.                programs  that  will  eventually be transported to
  2683.                standard C!  
  2684.  
  2685.  
  2686.                The "switch" statement behaves as follows: 
  2687.  
  2688.  
  2689.                1) evaluate the <expression>.  
  2690.  
  2691.                2) compare the results of <expression> to each of the 
  2692.                     <constant expression>'s after the "case's" 
  2693.                     sequentially from top to bottom.  
  2694.  
  2695.                3) if the value of <expression> matches one of the 
  2696.  
  2697.  
  2698.                                      - 44 -
  2699.  
  2700.  
  2701.      Small C Interpreter                                Programmer's Manual
  2702.  
  2703.  
  2704.                     <constant expression>'s, continue program 
  2705.                     execution with the statement immediately following 
  2706.                     the colon.  All other "case" and <constant 
  2707.                     expressions> are ignored.  
  2708.  
  2709.                4) if none of the <constant expression>'s match 
  2710.                     <expression>, jump to the <statement> immediately 
  2711.                     following the word "default" 
  2712.  
  2713.                5) if a "break" statement is encountered, jump to the 
  2714.                     end of the "switch" statement (the <statement> 
  2715.                     immediately following the }).  
  2716.  
  2717.  
  2718.                Although this seems complicated at first, a "switch" is 
  2719.           really just a multi-way program jump.  It allows you to jump 
  2720.           to anywhere within a statement, based on the value of an 
  2721.           expression.  
  2722.  
  2723.                Here's an example of a switch: 
  2724.  
  2725.  
  2726.                convert(n)
  2727.                {
  2728.                     char c;
  2729.                
  2730.                     puts("to decimal (d), hex (x) or octal (o) ?");
  2731.                     switch ( getchar() )
  2732.                     {
  2733.                     case 'd':
  2734.                          putd(n);
  2735.                          break;
  2736.                     case 'x':
  2737.                          putx(n);
  2738.                          break;
  2739.                     case 'o':
  2740.                          puto(n);
  2741.                          break;
  2742.                     default:
  2743.                          puts("what?\n");
  2744.                     }
  2745.                }
  2746.  
  2747.  
  2748.  
  2749.                                      NOTE                                        NOTE:
  2750.  
  2751.                Standard C allows you to place the "default"  word
  2752.                anywhere  within the "switch", and program control
  2753.                will jump  there  only  after  all  of  the  "case
  2754.                <constant  expression>  :"'s have been checked and
  2755.                no match found.   Here  again,  SCI  dares  to  be
  2756.  
  2757.  
  2758.                                      - 45 -
  2759.  
  2760.  
  2761.      Small C Interpreter                                Programmer's Manual
  2762.  
  2763.  
  2764.                different!  If a "default" is encountered before a 
  2765.                matching  "case",  the  program continues with the
  2766.                <statement> following the "default".    Therefore,
  2767.                it  is  a good idea to always place your "default"
  2768.                statements at the end of the "switch".  
  2769.  
  2770.  
  2771.  
  2772.  
  2773.  
  2774.  
  2775.  
  2776.  
  2777.  
  2778.  
  2779.  
  2780.  
  2781.  
  2782.  
  2783.  
  2784.  
  2785.  
  2786.  
  2787.  
  2788.  
  2789.  
  2790.  
  2791.  
  2792.  
  2793.  
  2794.  
  2795.  
  2796.  
  2797.  
  2798.  
  2799.  
  2800.  
  2801.  
  2802.  
  2803.  
  2804.  
  2805.  
  2806.  
  2807.  
  2808.  
  2809.  
  2810.  
  2811.  
  2812.  
  2813.  
  2814.  
  2815.  
  2816.  
  2817.  
  2818.                                      - 46 -
  2819.  
  2820.  
  2821.      Small C Interpreter                                Programmer's Manual
  2822.  
  2823.  
  2824.      13. Arrays 
  2825.  
  2826.  
  2827.                An array in C is a block of contiguous memory locations 
  2828.           (meaning they are located "one after the other" in memory) 
  2829.           that all have the same type ("char" or "int") and can be 
  2830.           accessed individually.  These individual data items in an 
  2831.           array are known as the array's "elements".  You have already 
  2832.           used arrays earlier, in your very first C program, namely 
  2833.           the sequence of ASCII characters in the string "hello, 
  2834.           world\n".  The array's elements are the ASCII characters 
  2835.           'h', 'e', 'l', etc.  This array however, could not be used 
  2836.           to store any information other than that sequence of 
  2837.           characters, just like the integer constant 5 let's say, can 
  2838.           not be used to store a different number.  In this section we 
  2839.           will show you how to create and use arrays for data storage 
  2840.           and retrieval.  
  2841.  
  2842.                Arrays are declared in a similar fashion as simple 
  2843.           variables, but following the array's name you must indicate 
  2844.           how many elements the array will have.  The size of an array 
  2845.           is constant, once it has been declared it can not be 
  2846.           changed.  Below is an example of an array declaration 
  2847.  
  2848.  
  2849.                char vartable[15], macnam[100];
  2850.  
  2851.  
  2852.                This statement declares two arrays that have 15 and 100 
  2853.           elements respectively.  The square brackets ([ and ]) 
  2854.           identifies the variable as being an array, they are also 
  2855.           required when you wish to access one of the array's 
  2856.           elements: 
  2857.  
  2858.  
  2859.                c = vartable[ 5 ];
  2860.  
  2861.  
  2862.                In C, array elements are counted from zero instead of 
  2863.                                                 _____                        one, so the above statement takes the sixth element of 
  2864.           "vartable" and stores it in the variable "c". To access the 
  2865.           _____                                                   first element of the array, we would write: 
  2866.  
  2867.  
  2868.                vartable[0] = 35;
  2869.  
  2870.                             ____                                           Consequently, the last element of the array would be 
  2871.                              ___                                                 "vartable[14]" and not "vartable[15]". In fact, if you did 
  2872.           attempt to store a number in "vartable[15]", you would 
  2873.           overwrite some unknown location in memory that was already 
  2874.           being used as storage for another variable or, worse yet, 
  2875.           that was part of your program code.  The results of 
  2876.  
  2877.  
  2878.                                      - 47 -
  2879.  
  2880.  
  2881.      Small C Interpreter                                Programmer's Manual
  2882.  
  2883.  
  2884.           overrunning a C array like this are unpredictable and are 
  2885.           dependent on the environment the C program is running in 
  2886.           (the type of machine, the C compiler used, etc.) 
  2887.  
  2888.                When the name of an array is used by itself without the 
  2889.           square brackets as in: 
  2890.  
  2891.  
  2892.                i = vartable + 5;
  2893.  
  2894.           it is taken to be a pointer to the first element of the 
  2895.           array.  In the example above, "i" would be assigned the 
  2896.           ______ ________                                        ___             memory location of the sixth element in the array, and not 
  2897.           ___ _____                                       the value of this memory location.  
  2898.  
  2899.                The Library Function "gets()" reads a line of input 
  2900.           from the console keyboard and places the characters at the 
  2901.           address pointed to by its argument.  This function waits for 
  2902.           the user to hit a carriage return before it returns to the 
  2903.           caller.  The input line is always terminated with a zero 
  2904.           byte by "gets()" and the carriage return is stripped out.  
  2905.           This makes it suitable for printing by its partner, 
  2906.           "puts()".  Try the following program: 
  2907.  
  2908.  
  2909.                greet()
  2910.                {
  2911.                     char name[ 80 ];
  2912.                
  2913.                     puts("hello, what's your name? ");
  2914.                     gets( name );
  2915.                     puts("nice to meet you, ");
  2916.                     puts( name );
  2917.                     puts(". Have a nice day!\n");
  2918.                }
  2919.  
  2920.  
  2921.  
  2922.  
  2923.  
  2924.  
  2925.  
  2926.  
  2927.  
  2928.  
  2929.  
  2930.  
  2931.  
  2932.  
  2933.  
  2934.  
  2935.  
  2936.  
  2937.  
  2938.                                      - 48 -
  2939.  
  2940.  
  2941.      Small C Interpreter                                Programmer's Manual
  2942.  
  2943.  
  2944.      14. Pointers 
  2945.  
  2946.  
  2947.                The last example above leads us directly into our next 
  2948.           discussion.  In C, you have the ability to access a memory 
  2949.           location by "pointing" at it with a variable.  This type of 
  2950.           variable is known as a "pointer" in C.  
  2951.  
  2952.  
  2953.                                      NOTE                                        NOTE:
  2954.  
  2955.                The number of bytes of storage a pointer  variable
  2956.                needs  depends on the environment the C program is
  2957.                running in.  All 8-bit personal  computers  (8080,
  2958.                z80,   6502,   etc.)   use  2  bytes  for  pointer
  2959.                variables.  The IBM-PC which has an 8088  CPU  may
  2960.                use  either  2  or  4 bytes for pointer variables,
  2961.                depending on the C compiler used.  SCI always uses 
  2962.                2 bytes.  
  2963.  
  2964.  
  2965.                C knows about the type of variable being pointed at 
  2966.           from the pointer's declaration: 
  2967.  
  2968.  
  2969.                char *char_pointer;
  2970.                int *int_pointer;
  2971.  
  2972.  
  2973.                Above we declared two variables, "char_pointer" and 
  2974.           "int_pointer".  The asterisk (*) in the declaration 
  2975.           statement identifies the variables as being pointers.  the 
  2976.           "char" and "int" keywords define the type of variable that 
  2977.           the pointer points to.  To illustrate: 
  2978.  
  2979.  
  2980.                i = *int_pointer;
  2981.  
  2982.  
  2983.                                        _______                                     This would retrieve the integer (two bytes in SCI) 
  2984.                                                         ________                found at the memory location addressed by the contents of 
  2985.           "int_pointer", and store it in "i". In this example, we 
  2986.           can't tell what will be stored in "i" because we don't know 
  2987.           what the contents of "int_pointer" is.  Recall from an 
  2988.           earlier discussion that SCI always initializes its variables 
  2989.           to zero so in this case, "i" would contain the two bytes 
  2990.           found in memory locations zero and one 
  2991.  
  2992.                Unless you know what is in memory locations zero and 
  2993.           one, this information is not very useful.  The power of 
  2994.           pointers lies in the fact that they can be made to point at 
  2995.           an array, like this: 
  2996.  
  2997.  
  2998.                                      - 49 -
  2999.  
  3000.  
  3001.      Small C Interpreter                                Programmer's Manual
  3002.  
  3003.  
  3004.                char vartable[15], *cp;
  3005.                
  3006.                cp = vartable;
  3007.                c = *cp;
  3008.                cp = cp+1;
  3009.                d = *cp;
  3010.                cp = cp+1;
  3011.                e = *cp;
  3012.  
  3013.  
  3014.                Here we have set the character pointer "cp" to point at 
  3015.           the first element of the array "vartable", and assigned the 
  3016.           ________                                                               contents of this first element to the variable "c" just by 
  3017.           letting "cp" point at it.  By simply adding one to "cp" we 
  3018.           have made it to point at the next element in "vartable".  
  3019.  
  3020.  
  3021.      14.1. Lvalues and Rvalues Revisited 
  3022.  
  3023.  
  3024.                Pointers are useful because they can be changed (bent?) 
  3025.           to address any location in memory whereas arrays are fixed 
  3026.           and always point to their first element.  For example, if 
  3027.           your tried to do this: 
  3028.  
  3029.  
  3030.                char a[10];
  3031.                
  3032.                a = a + 1;
  3033.  
  3034.  
  3035.                                                                ____                  you would get an error message.  The C language does 
  3036.           ___ _____ ___ __ ______ ___ _____ __ __ _____ ________                  not allow you to change the value of an array variable.  If 
  3037.           it did there might be the possibility of your program 
  3038.           "forgetting" where the data in the array is located.  Thus 
  3039.           arrays can be put in the same category as strings and 
  3040.           integer constants, namely "rvalues" (see an earlier 
  3041.           discussion on Lvalues and Rvalues).  
  3042.  
  3043.                The attempt to change the array variable "a" in the 
  3044.           example above would therefore reward you with a "need an 
  3045.           lvalue" error message from the SCI interpreter.  
  3046.  
  3047.                Pointers on the other hand are more analagous to 
  3048.           variables - they can be modified and are therefore 
  3049.           considered to be "lvalues".  
  3050.  
  3051.  
  3052.      14.2. Pointer Operator 
  3053.  
  3054.  
  3055.                The asterisk in the examples above is known as the 
  3056.  
  3057.  
  3058.                                      - 50 -
  3059.  
  3060.  
  3061.      Small C Interpreter                                Programmer's Manual
  3062.  
  3063.  
  3064.           "pointer" operator.  This is a unary operator and is used in 
  3065.           the same manner as the negation (-) unary operator.  The 
  3066.           pointer operation tells C to treat its associated pointer 
  3067.           variable as a memory address and to store or retrieve the 
  3068.                                                     _______                  data item at that address.  Note that the operand of a 
  3069.           pointer operator must have been declared as a pointer, or C 
  3070.           will complain.  This is in your own best interest because we 
  3071.           humans tend to forget little details like this.  For 
  3072.           example, if you wrote: 
  3073.  
  3074.  
  3075.                char c, d;
  3076.                
  3077.                d = *c;
  3078.  
  3079.           
  3080.           you would get a "not a pointer" error message from SCI.  
  3081.  
  3082.                Now, try typing in this little program using the SCI 
  3083.           editor: 
  3084.  
  3085.  
  3086.                prints(s)
  3087.                char *s;
  3088.                {
  3089.                     while(*s)
  3090.                     {
  3091.                          putchar(*s);
  3092.                          s=s+1;
  3093.                     }
  3094.                }
  3095.  
  3096.  
  3097.                The Library Function "putchar()" accepts a single 
  3098.           argument and prints the ASCII representation of this 
  3099.           argument to the console screen.  This program takes a 
  3100.           pointer to a character string as an argument.  Then, while 
  3101.           the character being pointed at is non-zero, "putchar()" 
  3102.           prints the character onto the console.  The pointer is then 
  3103.           incremented (s=s+1) so that it points at the next character 
  3104.           in the string.  Now execute the following command from the 
  3105.           shell: 
  3106.  
  3107.  
  3108.                > prints("hello, world\n");
  3109.  
  3110.  
  3111.                This should have resulted in the words "hello, world" 
  3112.           printed on the console.  
  3113.  
  3114.                Except for the fact that pointers may be changed and 
  3115.           arrays may not, C treats both of them identically.  For 
  3116.  
  3117.  
  3118.                                      - 51 -
  3119.  
  3120.  
  3121.      Small C Interpreter                                Programmer's Manual
  3122.  
  3123.  
  3124.           example if we have the following two data declarations: 
  3125.  
  3126.  
  3127.                char c, ca[ 10 ];
  3128.                char *cp;
  3129.  
  3130.           we can choose to view the array variable "ca" as a pointer, 
  3131.           and the pointer variable "cp" as an array in our programs, 
  3132.           like so: 
  3133.  
  3134.  
  3135.                c = *ca;
  3136.                cp[ 5 ] = c;
  3137.  
  3138.  
  3139.                So, we could have written the sample program from 
  3140.           before like this: 
  3141.  
  3142.  
  3143.                prints(s)
  3144.                char *s;
  3145.                {
  3146.                     int i;
  3147.                
  3148.                     for ( i=0; s[i]; i=i+1 )
  3149.                          putchar( s[i] );
  3150.                }
  3151.  
  3152.  
  3153.                This would have left the pointer argument "s" unaltered 
  3154.           when the "for" loop was finished.  This is sometimes 
  3155.           necessary, as in the following example: 
  3156.  
  3157.  
  3158.                prints10(s)
  3159.                char *s;
  3160.                {
  3161.                     int i, j;
  3162.                
  3163.                     for ( j=0; j<10; j=j+1 )
  3164.                     {
  3165.                          for ( i=0; s[i]; i=i+1 )
  3166.                               putchar( s[i] );
  3167.                     }
  3168.                }
  3169.  
  3170.           Here the string passed to "prints10()" is printed on the 
  3171.           console ten times.  If we had incremented the character 
  3172.           pointer "s" instead of using the index "i", then the second 
  3173.           time through the outer loop would have started with "s" 
  3174.           pointing to the character after the end of the string.  
  3175.  
  3176.  
  3177.  
  3178.                                      - 52 -
  3179.  
  3180.  
  3181.      Small C Interpreter                                Programmer's Manual
  3182.  
  3183.  
  3184.      14.2.1. Pointer Expressions 
  3185.  
  3186.  
  3187.                We stated that C knows the type of data item a pointer 
  3188.           is pointing to ("char" or "int"). Being a rather dumb (and 
  3189.           therefore compact) interpreter, SCI does not know what type 
  3190.           of data item is being pointed at when the pointer is hidden 
  3191.           in an expression somewhere, like so: 
  3192.  
  3193.  
  3194.                i = *(ip + 5);
  3195.  
  3196.  
  3197.                In this example we are trying to retrieve the data item 
  3198.           pointed at by "ip" and offset by 5. If "ip" was a pointer to 
  3199.           an "int", we would think that we are retrieving the sixth 
  3200.           2-byte integer of the array pointed at by "ip". Physically, 
  3201.           we are interested in the tenth and eleventh bytes in the 
  3202.           array.  The above expression, however, will retrieve only 
  3203.           one byte for us (the sixth byte in the array) instead of 
  3204.           two, and from the wrong place in the array.  This is a 
  3205.           limitation only of SCI - most C compilers are smart enough 
  3206.           to know better and the above statement would have retrieved 
  3207.           the sixth "int" from the array, as expected.  
  3208.  
  3209.                On occasion you may wish to use integer constants as 
  3210.           pointers, like this: 
  3211.  
  3212.  
  3213.                char c;
  3214.                
  3215.                c = *0x0100;
  3216.  
  3217.  
  3218.                When a constant is used as the target of a pointer 
  3219.           operation, SCI will access the two bytes (an "int") at the 
  3220.           location specified by the value of the constant, in this 
  3221.           case at location 100 hex.  You can get as creative as you 
  3222.           want when using constants as pointers: 
  3223.  
  3224.  
  3225.                char c, offs;
  3226.                
  3227.                c = *((0x101 + offs) * 2);
  3228.  
  3229.  
  3230.                Note that SCI will allow you to use variables that have 
  3231.           not been declared as pointers in pointer expressions if they 
  3232.           are enclosed in parentheses as shown above.  
  3233.  
  3234.  
  3235.  
  3236.  
  3237.  
  3238.                                      - 53 -
  3239.  
  3240.  
  3241.      Small C Interpreter                                Programmer's Manual
  3242.  
  3243.  
  3244.                                      NOTE                                        NOTE:
  3245.  
  3246.                Standard C does not  allow  you  to  use  constant
  3247.                expressions as pointers, any attempt to do so will 
  3248.                usually result in an error message.  
  3249.  
  3250.  
  3251.  
  3252.      14.2.2. printf() 
  3253.  
  3254.           C functions do not intrinsically know whether their 
  3255.           arguments are printable strings or just an array or numbers, 
  3256.           like BASIC does.  Therefore there are no C functions that 
  3257.           are analogous to BASIC's PRINT statement which prints either 
  3258.           a number or a string depending on its argument.  The 
  3259.           standard C Library Function "printf()", however, performs a 
  3260.           print operation similar to BASIC's PRINT statement.  
  3261.           "Printf", which is read as "print-eff", stands for "print 
  3262.           formatted".  It is the most unusual standard C function 
  3263.           because it accepts a variable number of arguments, depending 
  3264.           on the contents of its first argument.  The first argument 
  3265.           to "printf" is a string of characters and is known as the 
  3266.           "control string".  "Printf" works like this: it scans 
  3267.           through the characters in the control string and prints them 
  3268.           out on the console screen; if a percent symbol (%) is 
  3269.           encountered in the control string, the character following 
  3270.                                                ________                     the "%" determines how printf's next argument will be 
  3271.           processed.  For example, if the character following the "%" 
  3272.           is a lower case letter "s", the next argument is assumed to 
  3273.           be a character string and is printed out to the console 
  3274.           instead of the "%s" character combination.  A "%d" 
  3275.           combination in the control string takes its next argument to 
  3276.           be an integer and prints its decimal value.  "Printf" keeps 
  3277.           track of which arguments have already been printed by a 
  3278.           "%-letter" combination, so that the next "%-letter" 
  3279.           combination affects the next argument in the argument list.  
  3280.  
  3281.                For example, try the following command from the shell: 
  3282.           
  3283.         printf("%s, did you know %d * %d is %d?\n","Bob",376,49,376*49)
  3284.  
  3285.                The "%s" conversion treats the second argument, "Bob" 
  3286.           as a string (which it is!) and prints it; the first "%d" 
  3287.           grabs the next argument in the list (376) and prints it as a 
  3288.           decimal number; the second "%d" prints 49 as a decimal 
  3289.           number; finally, the third "%d" takes the product of 376 and 
  3290.           49 and prints it as a decimal number.  What should have 
  3291.           appeared on your screen is: 
  3292.  
  3293.  
  3294.                Bob, did you know 376 * 49 is 18424?
  3295.  
  3296.  
  3297.  
  3298.                                      - 54 -
  3299.  
  3300.  
  3301.      Small C Interpreter                                Programmer's Manual
  3302.  
  3303.  
  3304.           "Printf" also recognizes these other conversion codes: 
  3305.  
  3306.  
  3307.                 x                                                                      %x - prints its argument as a hexadecimal number.  The 
  3308.                     characters "0x" do not appear in the printed 
  3309.                     number - you must add them if needed, like so: 
  3310.  
  3311.  
  3312.                          printf( "%d = 0x%x\n", 376, 376 )
  3313.  
  3314.  
  3315.                 o                                                             %o - prints its argument as an octal number.  
  3316.  
  3317.                 c                                                                %c - prints its argument as an ASCII character.  
  3318.  
  3319.  
  3320.  
  3321.      14.3. Address Operator 
  3322.  
  3323.  
  3324.                In an earlier discussion about the scope of variables, 
  3325.           we said when a variable is passed to a function, the called 
  3326.           function creates a clone of the caller's variable and copies 
  3327.           its contents into this local variable.  This way the 
  3328.           function can not alter the contents of the caller's 
  3329.           variable.  How then can we have a function alter the 
  3330.           contents of our local variables if it becomes necessary?  
  3331.           There are several options open to us: 1) write the function 
  3332.           so that it returns a value which we can then assign to our 
  3333.           local variable, 2) have the function put the value into a 
  3334.           global variable which we can access, or 3) pass the function 
  3335.           the address of our local variable.  The first option only 
  3336.           allows the function to pass back one piece of information, 
  3337.           thus limiting its usefulness.  Option 2 is an acceptable 
  3338.           method but forces the function to become more dependent upon 
  3339.           the entire program structure.  This is fine for 
  3340.           application-specific functions, but severly restricts the 
  3341.           modularity of general purpose functions.  The accepted 
  3342.           method is to pass the function the address of our variable 
  3343.           using the "address operator", "&", like so: 
  3344.  
  3345.  
  3346.  
  3347.  
  3348.  
  3349.  
  3350.  
  3351.  
  3352.  
  3353.  
  3354.  
  3355.  
  3356.  
  3357.  
  3358.                                      - 55 -
  3359.  
  3360.  
  3361.      Small C Interpreter                                Programmer's Manual
  3362.  
  3363.  
  3364.                prog()
  3365.                {
  3366.                     char c;
  3367.                
  3368.                     func( &c ); # call "func()", pass the address of "c"
  3369.                }
  3370.                func( ptr )
  3371.                char *ptr;
  3372.                {
  3373.                     *ptr = 12;
  3374.                }
  3375.  
  3376.  
  3377.                The ampersand (&) as used above is a unary operator 
  3378.                                           _______                               that tells C we want to use the address of the associated 
  3379.                                   ________  __ _____ _____  ___             variable instead of its contents. In other words, the 
  3380.           _______ ________ ______ _ _______                               address operator yields a pointer to its associated 
  3381.           operand.  That's why we declared the argument to the 
  3382.           function "func()" as a pointer to a "char".  In the above 
  3383.           example then, the local variable "c" in "prog()" would have 
  3384.           been set to 12 after the call to "func()".  
  3385.  
  3386.                Extreme caution must be exercised when passing pointers 
  3387.           to variables like this.  If we had instead declared "ptr" as 
  3388.           a pointer to an "int" (int *ptr;) in the function, "func()", 
  3389.           then the assignment "*ptr = 12;" would have destroyed the 
  3390.           memory location following "c" and possibly caused the 
  3391.           program to crash.  
  3392.  
  3393.                Note that you may only use the address operator on 
  3394.           lvalues; this means only simple variables and pointers.  If 
  3395.           you try to use the address operator on a constant, a string 
  3396.           or an array you will evoke a "need an lvalue" error from 
  3397.           SCI.  
  3398.  
  3399.                Now enter and test this little program from the SCI 
  3400.           interpreter: 
  3401.  
  3402.  
  3403.  
  3404.  
  3405.  
  3406.  
  3407.  
  3408.  
  3409.  
  3410.  
  3411.  
  3412.  
  3413.  
  3414.  
  3415.  
  3416.  
  3417.  
  3418.                                      - 56 -
  3419.  
  3420.  
  3421.      Small C Interpreter                                Programmer's Manual
  3422.  
  3423.  
  3424.                words()
  3425.                {
  3426.                     char *word, *cp, linebuf[80];
  3427.                
  3428.                     puts("type some words: ");
  3429.                     gets(cp = linebuf);
  3430.                     while(cp) {
  3431.                          cp = parse(cp, &word);
  3432.                          puts("word = <");
  3433.                          puts(word);
  3434.                          puts(">\n");
  3435.                     }
  3436.                }
  3437.                
  3438.                parse(str,word)
  3439.                char *str;
  3440.                int *word;
  3441.                {
  3442.                     while(*str==' ')
  3443.                          ++str;
  3444.                     *word=str;
  3445.                     while(*str!=' ' && *str)
  3446.                          ++str;
  3447.                     if(*str==0)
  3448.                          return 0;
  3449.                     *str=0;
  3450.                     return str+1;
  3451.                }
  3452.  
  3453.           
  3454.           and from the shell execute the function "words()".  What 
  3455.           does this program do?  
  3456.  
  3457.  
  3458.      14.3.1. scanf() 
  3459.  
  3460.  
  3461.                The companion to the Library Function "printf()" is 
  3462.           "scanf()" (read "scan-eff").  This function performs the 
  3463.           reverse operation of "printf()", that is, it converts 
  3464.           strings and numbers read from the console keyboard and 
  3465.           places them into program variables.  This means that its 
  3466.                             ________                                            arguments must be pointers to the appropriate data type.  
  3467.  
  3468.                Examine the following program: 
  3469.  
  3470.  
  3471.  
  3472.  
  3473.  
  3474.  
  3475.  
  3476.  
  3477.  
  3478.                                      - 57 -
  3479.  
  3480.  
  3481.      Small C Interpreter                                Programmer's Manual
  3482.  
  3483.  
  3484.                getname()
  3485.                {
  3486.                     char firstname[20], lastname[20];
  3487.                     int zip;
  3488.                
  3489.                     puts("What is your first, last name and zipcode?");
  3490.                     scanf("%s %s %d", firstname, lastname, &zip );
  3491.                
  3492.                     printf("firstname = %s\n",firstname);
  3493.                     printf("lastname = %s\n",lastname);
  3494.                     printf("zipcode = %d\n",zip);
  3495.                }
  3496.  
  3497.  
  3498.                Scanf assumes that a string is a stream of consecutive 
  3499.           non-blank characters.  The function will not stop reading 
  3500.           input until all of its conversion (%-letter) codes have been 
  3501.           satisfied, or until an end of input (control-Z in MS-DOS) is 
  3502.                                                          __ ___                   encountered.  This means that carriage returns do not cause 
  3503.           scanf to quit reading and return to the caller.  Carriage 
  3504.           returns are simply treated as spaces and tabs, collectively 
  3505.           known as "white space".  In the program above, you could 
  3506.           have entered you first and last name on seperate lines if 
  3507.           you like, or on the same line seperated by one or more 
  3508.           spaces or tabs.  
  3509.  
  3510.                                _______                                                Notice that the address of the integer variable "zip" 
  3511.           was passed to scanf; do you now understand why?  If we had 
  3512.           used the following statement instead: 
  3513.  
  3514.  
  3515.                scanf( "%d", zip );
  3516.  
  3517.           
  3518.                    ________                                                  then the contents of "zip" would have been used as the 
  3519.           location where scanf would place an integer value.  If the 
  3520.           contents of "zip" had been zero, then memory locations zero 
  3521.           and one would have been altered by scanf, and would have 
  3522.           possibly damaged the operating system.  
  3523.  
  3524.  
  3525.  
  3526.  
  3527.  
  3528.  
  3529.  
  3530.  
  3531.  
  3532.  
  3533.  
  3534.  
  3535.  
  3536.  
  3537.  
  3538.                                      - 58 -
  3539.  
  3540.  
  3541.      Small C Interpreter                                Programmer's Manual
  3542.  
  3543.  
  3544.      15. Increment and Decrement Operators 
  3545.  
  3546.  
  3547.                As we have already seen, we can use several methods to 
  3548.           access elements in an array.  Let's say we had an array and 
  3549.           wanted to access its elements sequentially, one after the 
  3550.           other.  We could either declare a pointer to the array and 
  3551.           then increment the pointer by one; or we could declare an 
  3552.           integer variable to be used as an array index and increment 
  3553.           it each time by one, like so: 
  3554.  
  3555.  
  3556.                char a[10], *p;
  3557.                int i;
  3558.                
  3559.                # set all 10 elements in the array "a" to zero,
  3560.                # using a pointer:
  3561.                p=a;
  3562.                i=0;
  3563.                while(i<10)
  3564.                {
  3565.                     *p = 0;
  3566.                     p=p+1;
  3567.                     i=i+1;
  3568.                }
  3569.                
  3570.                # ...and using an index:
  3571.                i=0;
  3572.                while(i<10)
  3573.                {
  3574.                     a[i] = 0;
  3575.                     i=i+1;
  3576.                }
  3577.  
  3578.           Since these operations comes up often in programming, the C 
  3579.           language offers a very efficient method of incrementing and 
  3580.           decrementing varibles.  These are appropriately enough, 
  3581.           called the "increment" and "decrement" operators, "++" and 
  3582.           "--".  The increment/decrement operators are unary operators 
  3583.           and can appear either before or after a variable name, like 
  3584.           this: 
  3585.  
  3586.  
  3587.                int i;
  3588.                
  3589.                ++i;    # increment "i" by one
  3590.                i++;    # same thing
  3591.                --i;    # decrement "i" by one
  3592.                i--;    # and again
  3593.  
  3594.                                   ______                                          If the operator appears before the variable, it is known as 
  3595.                                                          _____                 a "pre-" increment or decrement; if it appears after the 
  3596.  
  3597.  
  3598.                                      - 59 -
  3599.  
  3600.  
  3601.      Small C Interpreter                                Programmer's Manual
  3602.  
  3603.  
  3604.           variable, it is a "post-" increment/decrement.  The 
  3605.                                                        ______                 pre-inc/dec operators perform their function before the 
  3606.           variable is used in the expression, whereas the post-inc/dec 
  3607.                                            _____                                   operators perform their function after the variable has been 
  3608.           used in the expression.  This is best explained with an 
  3609.           example: 
  3610.  
  3611.  
  3612.                incdec()
  3613.                {
  3614.                     int i;
  3615.                
  3616.                     i = 0;
  3617.                     putd( ++i );
  3618.                
  3619.                     i = 0;
  3620.                     putd( i++ );
  3621.                }
  3622.  
  3623.  
  3624.                The first instance of "putd()" would print a 1 - the 
  3625.           variable "i" was increment by one before its value was 
  3626.           passed to "putd()".  Now we set "i" to zero again and the 
  3627.           second call to "putd()" will print a 0. This is because the 
  3628.           post-increment operator passes the value of "i" to the 
  3629.                             ______                                          function "putd()" before it gets incremented by one.  
  3630.  
  3631.                These operators are very handy for quickly scanning 
  3632.           through an array like this: 
  3633.  
  3634.  
  3635.                prints(s)
  3636.                char *s;
  3637.                {
  3638.                     while ( *s )
  3639.                          putchar( *s++ );
  3640.                }
  3641.  
  3642.  
  3643.                When using the increment/decrement operators on 
  3644.           pointers, SCI knows what data type the pointer is 
  3645.           referencing and adjusts the pointer so that it points to the 
  3646.           next/previous data item.  In other words, when incrementing 
  3647.           a pointer to an integer, the pointer is incremented by 2 
  3648.           instead of one so that it points to the next integer.  If we 
  3649.           wanted to print out all the numbers in an integer array, we 
  3650.           might do something like this: 
  3651.  
  3652.  
  3653.  
  3654.  
  3655.  
  3656.  
  3657.  
  3658.                                      - 60 -
  3659.  
  3660.  
  3661.      Small C Interpreter                                Programmer's Manual
  3662.  
  3663.  
  3664.                dump()
  3665.                {
  3666.                     int array[ 10 ], *ap;
  3667.                
  3668.                     ap = array;
  3669.                     for ( i=0; i<10; ++i )
  3670.                          printf( "%d\n", *ap++ );
  3671.                }
  3672.  
  3673.  
  3674.  
  3675.  
  3676.  
  3677.  
  3678.  
  3679.  
  3680.  
  3681.  
  3682.  
  3683.  
  3684.  
  3685.  
  3686.  
  3687.  
  3688.  
  3689.  
  3690.  
  3691.  
  3692.  
  3693.  
  3694.  
  3695.  
  3696.  
  3697.  
  3698.  
  3699.  
  3700.  
  3701.  
  3702.  
  3703.  
  3704.  
  3705.  
  3706.  
  3707.  
  3708.  
  3709.  
  3710.  
  3711.  
  3712.  
  3713.  
  3714.  
  3715.  
  3716.  
  3717.  
  3718.                                      - 61 -
  3719.  
  3720.  
  3721.      Small C Interpreter                                Programmer's Manual
  3722.  
  3723.  
  3724.      16. A Tour Through the File I/O Functions 
  3725.  
  3726.  
  3727.                The formal definition of the C language does not really 
  3728.           include any of the Library Functions we have discussed so 
  3729.           far.  However, most of these have become defacto standards 
  3730.           and are considered a part of the language's support 
  3731.           library.  Although the exact usage of support functions may 
  3732.           vary from one compiler implementation to the next, most C 
  3733.           compilers adhere to a "standard" to some degree.  This 
  3734.           section discusses SCI's implementation of the file I/O 
  3735.           functions which is fairly compatible with the "standards" 
  3736.           proposed by the authors of the C language.  
  3737.  
  3738.                This section only attempts to clarify some points 
  3739.           concerning the file I/O functions and is not meant as a 
  3740.           reference.  Please refer to the section in the User's Manual 
  3741.           titled "The Library Function" for exact details about these 
  3742.           functions.  
  3743.  
  3744.  
  3745.  
  3746.      16.1. fopen() 
  3747.  
  3748.  
  3749.                Before a file can be used (read from or written to), it 
  3750.           must first be "opened" with the Library Function "fopen()". 
  3751.           Opening a file ensures that the file exists and is 
  3752.           readable/writable and prepares internal data structures for 
  3753.           dealing with the file.  Before a C program starts up, three 
  3754.           "files" are opened for it by the "operating system", these 
  3755.           are known as the "standard input", "standard output" and 
  3756.           "standard error" file.  These usually default to the user's 
  3757.           console keyboard and screen.  The "standard error" file is 
  3758.           an output file and always defaults to the user's console 
  3759.           screen.  It is usually used by the program to display error 
  3760.           messages.  The reason we like to have two output files is 
  3761.           because we don't want to intermix program error and 
  3762.           informational messages with program output data, and to 
  3763.           insure that error messages always appear on the user's 
  3764.           console.  
  3765.  
  3766.                To open a file, "fopen()" must be called with two 
  3767.           arguments: the file name, and a character string that 
  3768.           defines how the file is to be accessed.  For example, 
  3769.  
  3770.  
  3771.                int channel;
  3772.                
  3773.                channel = fopen( "SHELL.SCI", "r" );
  3774.  
  3775.           would open the file "SHELL.SCI" for reading ("r").  MS-DOS 
  3776.  
  3777.  
  3778.                                      - 62 -
  3779.  
  3780.  
  3781.      Small C Interpreter                                Programmer's Manual
  3782.  
  3783.  
  3784.           allows the file name to be in upper or lower case, other 
  3785.           operating systems may not be so indifferent about file 
  3786.           names.  The second string, known as the "open mode", must 
  3787.           contain either a lower case "r" to open the file for 
  3788.           reading, "w" for writing or "a" for appending.  When a file 
  3789.           is opened for reading, it must already exist or "fopen()" 
  3790.           will return an error code.  If a file is opened for writing, 
  3791.           it may or may not exist; if it does exist, it is first 
  3792.           deleted before the open.  If a file is opened for appending 
  3793.           and the file exists, it is opened for writing, but data is 
  3794.           written to the current end of the file.  If the file does 
  3795.           not exist, an open for append acts like an open for write.  
  3796.           You may also open a file for both reading and writing, 
  3797.           meaning you may intermix read and write functions on the 
  3798.           same file, but see the section on the Library Functions for 
  3799.           more information.  
  3800.  
  3801.                The value returned by "fopen()" is an integer known as 
  3802.           the "channel number" and points to the previously mentioned 
  3803.           internal file control data structure.  This channel number 
  3804.           is then used by the other file read/write functions to 
  3805.           access the file.  If "fopen()" was unable to find the file 
  3806.           (file opened for reading) or the file could not be created 
  3807.           (file opened for writing), it returns a zero, indicating 
  3808.           failure.  
  3809.  
  3810.                The special channel numbers 1, 2 and 3 may be used to 
  3811.           read and write from/to the standard input, output and error 
  3812.           files.  These channel numbers may be used with the file 
  3813.           read/write routines at any time, unless of course you have 
  3814.           closed these channels.  
  3815.  
  3816.  
  3817.      16.2. fclose() 
  3818.  
  3819.           When a file is no longer needed, it should be "closed" by 
  3820.           the program.  Closing a file ensures that the file is safely 
  3821.           stored on disk and it frees up the internal file control 
  3822.           data structure.  
  3823.  
  3824.                This function expects a single argument, the file 
  3825.           pointer: 
  3826.  
  3827.  
  3828.                fclose( fp );
  3829.  
  3830.           
  3831.           and returns a zero if the file was closed successfully, or a 
  3832.           -1 if an error occured (the file was never opened, disk is 
  3833.           write protected, etc.).  
  3834.  
  3835.  
  3836.  
  3837.  
  3838.                                      - 63 -
  3839.  
  3840.  
  3841.      Small C Interpreter                                Programmer's Manual
  3842.  
  3843.  
  3844.      16.3. fgetc() and fputc() 
  3845.  
  3846.  
  3847.                The functions "fgetc()" and "fputc()" are used to read 
  3848.           and write respectively a single character from/to a file.  
  3849.           Both of these functions advance a "file position pointer" 
  3850.           which points to the next character to be read/written 
  3851.           to/from the file.  This file position pointer is one of the 
  3852.           items in the aforementioned internal file control data 
  3853.           structure.  These functions are used like so: 
  3854.  
  3855.  
  3856.                copy(fromfile,tofile)
  3857.                char *fromfile, *tofile;
  3858.                {
  3859.                     int fromchannel, tochannel, c;
  3860.                
  3861.                     fromchannel = fopen( fromfile, "r" );
  3862.                     tochannel = fopen( tofile, "w" );
  3863.                     while ( (c = fgetc( fromchannel )) != -1 )
  3864.                          fputc( c, tochannel );
  3865.                     fclose( fromchannel );
  3866.                     fclose( tochannel );
  3867.                }
  3868.  
  3869.  
  3870.                This little program copies the file whose name is the 
  3871.           string at "fromfile" to the file whose name is at "tofile".  
  3872.  
  3873.                The function "fgets()" returns the character that was 
  3874.           read from the file (a single byte value from 0 to 255) or a 
  3875.           minus one if the end of the file was reached or if some 
  3876.           other error occured.  The function "fputc()" returns the 
  3877.           character that was written or a minus one if an error 
  3878.           occured.  
  3879.  
  3880.  
  3881.      16.4. fgets() and fputs() 
  3882.  
  3883.  
  3884.                You may also read and write disk files a "line" at a 
  3885.           time with the functions "fgets()" and "fputs()". A "line" is 
  3886.           a sequence of characters in the file that end with a newline 
  3887.           ("\n") character.  These are similar to the functions 
  3888.           "gets()" and "puts()", which read and write from/to the 
  3889.           standard input and standard output, with the exception that 
  3890.           the newline character is copied into the line input buffer 
  3891.           by "fgets()" and a newline is automatically appended to 
  3892.           every string written out to the file by "fputs()".  
  3893.  
  3894.                Note that the two functions fputs("hello",2) and 
  3895.           puts("hello") are identical.  
  3896.  
  3897.  
  3898.                                      - 64 -
  3899.  
  3900.  
  3901.      Small C Interpreter                                Programmer's Manual
  3902.  
  3903.  
  3904.      16.5. fread() and fwrite() 
  3905.  
  3906.  
  3907.                Sometimes it is useful to be able to read or write a 
  3908.           file in arbitrarily long "blocks".  For example, suppose we 
  3909.           wanted to store an array of integer numbers in a file.  The 
  3910.           character read/write functions ("fgetc()" and "fputc()") 
  3911.           would work but would be less efficient than writing several 
  3912.           characters at a time.  The functions "fread()" and 
  3913.           "fwrite()" are ideal for these situations: 
  3914.  
  3915.  
  3916.                sortfile()
  3917.                {
  3918.                     int array[ 100 ];
  3919.                     int channel;
  3920.                
  3921.                     channel = fopen( "NUMBERS.DAT", "r" );
  3922.                     fread( array, 200, channel );
  3923.                     fclose( channel );
  3924.                
  3925.                     sort( array, 100 );
  3926.                
  3927.                     channel = fopen( "NUMBERS.DAT", "w" );
  3928.                     fwrite( array, 200, channel );
  3929.                     fclose( channel );
  3930.                }
  3931.                
  3932.                sort(a,n)
  3933.                int a[], n;
  3934.                {
  3935.                     int temp, i, j;
  3936.                
  3937.                     for ( i=0; i<n-2; ++i ) {
  3938.                          for ( j=i; j<n-1; ++j ) {
  3939.                               if ( a[j] > a[j+1] ) {
  3940.                                    temp=a[j];
  3941.                                    a[j]=a[j+1];
  3942.                                    a[j+1]=temp;
  3943.                               }
  3944.                          }
  3945.                     }
  3946.                }
  3947.  
  3948.           This program reads an array of 100 numbers from a file, 
  3949.           sorts them in numeric order and writes them back to the 
  3950.           file.  Note that we asked "fread()" and "fwrite()" for 200 
  3951.           bytes.  Since the array consists of 100 integers and each 
  3952.           integer is 2 bytes, the array is 200 bytes long.  
  3953.  
  3954.                Also, be sure to close a file when it is no longer 
  3955.           needed.  If we had neglected to close the file after the 
  3956.  
  3957.  
  3958.                                      - 65 -
  3959.  
  3960.  
  3961.      Small C Interpreter                                Programmer's Manual
  3962.  
  3963.  
  3964.           "fopen()" for reading, the second call to "fopen()" would 
  3965.           have altered our file pointer.  The value of the first file 
  3966.           pointer would have been destroyed and the internal file 
  3967.           control data structure would have been lost in limbo 
  3968.           forever.  Although this wouldn't have caused any damage, it 
  3969.           is very sloppy programming.  Keep in mind that you have only 
  3970.           10 file control data structures available.  
  3971.  
  3972.  
  3973.      16.6. fseek() and ftell() 
  3974.  
  3975.  
  3976.                All of the file read/write functions advance an 
  3977.           invisible "file position pointer" which determines where in 
  3978.           the file the next character will be read from or written 
  3979.           to.  Sometimes it is necessary to re-read a character or 
  3980.           group of characters in a file, or to write over the current 
  3981.           contents in a file with new data.  The function "fseek()" 
  3982.           can be used to relocate the file position pointer to 
  3983.           anywhere within the file, and allow you to re-read or 
  3984.           re-write data in the file as necessary.  
  3985.  
  3986.                Ftell simply returns the current value of the file 
  3987.           position pointer.  
  3988.  
  3989.                Examine the following sample program: 
  3990.  
  3991.  
  3992.                link()
  3993.                {
  3994.                     int start, current, inchannel, outchannel, c;
  3995.                
  3996.                     inchannel = fopen( "RAW.DAT", "r" );
  3997.                     outchannel = fopen( "LINKED.DAT", "wr" );
  3998.                
  3999.                     start = 0;
  4000.                     fwrite( &start, 2, outchannel );
  4001.                     while ( (c=fgetc( inchannel )) != -1 ) {
  4002.                          if ( fputc( c, outchannel ) == 0x00ff )
  4003.                               current = ftell( outchannel );
  4004.                               fseek( outchannel, start, 0 );
  4005.                               fwrite( ¤t, 2, outchannel );
  4006.                               fseek( outchannel, current, 0 );
  4007.                               start = current;
  4008.                          }
  4009.                     }
  4010.                     fclose( inchannel );
  4011.                     fclose( outchannel );
  4012.                }
  4013.  
  4014.           This program copies the file RAW.DAT to LINKED.DAT. Each 
  4015.           time a byte of all one's (FF hexadecimal) is encountered in 
  4016.  
  4017.  
  4018.                                      - 66 -
  4019.  
  4020.  
  4021.      Small C Interpreter                                Programmer's Manual
  4022.  
  4023.  
  4024.           RAW.DAT, the program backs up to the previous start location 
  4025.           in LINKED.DAT (indicated in the variable "start") and 
  4026.           inserts the file's current file position pointer 
  4027.           ("current").  In other words, the program creates a file 
  4028.           identical to RAW.DAT except that the data in the file 
  4029.           contains information that tells where all of the 0xff's are 
  4030.           located within the file - a linked list.  
  4031.  
  4032.                Since SCI only supports integer variables, this limits 
  4033.           the maximum range of absolute file positioning available 
  4034.           with "fseek()" to 32767 from the beginning or end of the 
  4035.           file.  You can however, position the file pointer to within 
  4036.                                   _______                                        +/-32767 bytes from the current position.  This allows you 
  4037.           to position the file pointer anywhere within the file, no 
  4038.           matter how large the file is.  Standard C uses "long" data 
  4039.           variables instead of "int"'s for specifying the file 
  4040.           position offset.  Long's are usually twice the size of an 
  4041.           "int" (four bytes instead of two), which gives you a much 
  4042.           larger range of absolute file positioning.  
  4043.  
  4044.  
  4045.  
  4046.  
  4047.  
  4048.  
  4049.  
  4050.  
  4051.  
  4052.  
  4053.  
  4054.  
  4055.  
  4056.  
  4057.  
  4058.  
  4059.  
  4060.  
  4061.  
  4062.  
  4063.  
  4064.  
  4065.  
  4066.  
  4067.  
  4068.  
  4069.  
  4070.  
  4071.  
  4072.  
  4073.  
  4074.  
  4075.  
  4076.  
  4077.  
  4078.                                      - 67 -
  4079.  
  4080.  
  4081.      Small C Interpreter                                Programmer's Manual
  4082.  
  4083.  
  4084.      17. The Debuger 
  4085.  
  4086.  
  4087.                SCI provides a powerful program debugging facility that 
  4088.           allows you to execute your programs with complete control.  
  4089.           When the debuger is active, it takes control of your program 
  4090.           and allows you to step through the program in a controlled 
  4091.           fashion.  You have the option of either executing a line at 
  4092.           a time, or stop at any line in the program.  From the 
  4093.           debuger you can also examine and change program variables in 
  4094.           the middle of a program run, or execute any valid C 
  4095.           statement.  
  4096.  
  4097.                Besides being a reference for the SCI debug facility, 
  4098.           this section will introduce you to general debugging 
  4099.           strategies, and show you how you can use the SCI debuger to 
  4100.           gain a better knowledge of C program flow.  
  4101.  
  4102.  
  4103.      17.1. Introduction 
  4104.  
  4105.  
  4106.                The SCI debuger operates in what is known as "symbolic" 
  4107.           mode.  As you probably already know, a computer can not 
  4108.           directly execute program instructions written in the C (or 
  4109.           any other higher-level) language.  The C language 
  4110.           instructions must first be converted to machine language and 
  4111.           then executed by the computer.  This is the mode of 
  4112.           operation when using a C compiler.  Alternatively, the C 
  4113.           source code can be directly executed by a program known as 
  4114.           an "interpreter", which is exactly how SCI works.  A C 
  4115.           program that has been compiled is completely unreadable by 
  4116.           us humans - all resemblence to the original C code has been 
  4117.           stripped from the program since it is intended only for the 
  4118.           computer's "eyes". We say that the "symbolic" representation 
  4119.           of a machine readable program has been removed.  On the 
  4120.           other hand, since an interpreter always keeps a "symbolic" 
  4121.           (human readable) form of your program in memory, it is very 
  4122.           easy to follow the program as it is being executed by the 
  4123.           interpreter.  A debuger that has this ability to let the 
  4124.           human reader follow along as the program is executed by the 
  4125.           computer, is known as a "symbolic debuger".  
  4126.  
  4127.                There are basically two types of program errors that 
  4128.           can occur: unrecoverable and recoverable.  Unrecoverable 
  4129.           errors are typified by the computer's refusal to answer to 
  4130.           the programmer's desperate pounding on the keyboard - we say 
  4131.           that the computer has "locked up" and gone south for the 
  4132.           winter.  These errors may be caused by partial or complete 
  4133.           destruction of the program itself, or of the operating 
  4134.           system and usually require you to turn the computer off and 
  4135.           then on again.  Recoverable errors are the kind which do not 
  4136.  
  4137.  
  4138.                                      - 68 -
  4139.  
  4140.  
  4141.      Small C Interpreter                                Programmer's Manual
  4142.  
  4143.  
  4144.           allow the program to run to normal completion and return you 
  4145.           to either the operating system or to the calling program, or 
  4146.           simply "get stuck" in a never ending loop.  The category of 
  4147.           recoverable errors also include incorrect results: 
  4148.  
  4149.  
  4150.                YOU: what is 2 plus 2?
  4151.                COMPUTER: 5
  4152.  
  4153.           
  4154.           and unexpected results: 
  4155.  
  4156.  
  4157.                COMPUTER: shall I delete this file?
  4158.                YOU: No
  4159.                COMPUTER: OK, file deleted!
  4160.  
  4161.  
  4162.                For obvious reasons, SCI's built-in debuger is only 
  4163.           capable of dealing with recoverable errors.  
  4164.  
  4165.                The apporach to finding both of these types of errors 
  4166.           is basically the same: allow the program to run normally up 
  4167.           to the point just before it goes berzerk, then stop and look 
  4168.           at how it got there.  Usually, the hardest task is finding 
  4169.           that point where your program goes over the edge.  You have 
  4170.           two choices: either run the program from the very beginning, 
  4171.           one line at a time until something unexpected happens, or 
  4172.           allow the program to run normally and stop just before the 
  4173.           section of code that is suspect.  The method of executing a 
  4174.           program a line at a time is known as "single-stepping".  
  4175.           Running a program normally and having it stop at a given 
  4176.           line is known as "running to breakpoint".  The SCI debuger 
  4177.           allows you to use both of these approaches in any 
  4178.           combination.  
  4179.  
  4180.  
  4181.      17.2. Enabling the Debuger 
  4182.  
  4183.  
  4184.                The Library Function "trace" is used to turn the SCI 
  4185.           debuger on and off and may be called either from the shell 
  4186.           prompt or from within your program.  A single argument to 
  4187.           "trace" determines whether the debuger will be turned on or 
  4188.           off: if the argument is non-zero the debuger is turned on; 
  4189.           if zero, it is turned off.  Thus, your program would look 
  4190.           like this: 
  4191.  
  4192.  
  4193.  
  4194.  
  4195.  
  4196.  
  4197.  
  4198.                                      - 69 -
  4199.  
  4200.  
  4201.                Small C Interpreter                                Programmer's Manual
  4202.  
  4203.  
  4204.                     func()
  4205.                     {
  4206.                          int i;
  4207.                          .
  4208.                          .
  4209.                          .
  4210.                          trace(1);   # turn debuger ON
  4211.                          while(i<10)   # scrutinize this loop
  4212.                          {
  4213.                               .
  4214.                               .
  4215.                               .
  4216.                          }
  4217.                          trace(0);    # turn debuger OFF again
  4218.                     }
  4219.  
  4220.  
  4221.                You can also turn the debuger on directy from the 
  4222.           keyboard while a program is running.  By pressing the 
  4223.           <ESCAPE> key at any time, the program is stopped in mid 
  4224.           execution and the debuger is turned on.  Thus, if you have a 
  4225.           program that seems to be stuck in a forever loop, you can 
  4226.           get control and take a look at what's causing the problem.  
  4227.  
  4228.                When the debuger gets control of your program, it will 
  4229.           automatically display the line number and program text of 
  4230.           the next line to be executed.  It is important to realize 
  4231.           that the displayed program line has not yet been executed.  
  4232.           Directly below the displayed line is a circumflex that 
  4233.           points the first item in the line that will be executed.  
  4234.           For example, if you had more than one statement on a single 
  4235.           line, you might see: 
  4236.  
  4237.  
  4238.                 12:     i = 10;  putd(i);
  4239.                                      ^
  4240.  
  4241.  
  4242.                The debuger then displays its question mark (?) prompt 
  4243.           and waits for you to enter a command.  Debuger commands 
  4244.           always start with a dot (.) in the first column, followed by 
  4245.           a command mnemonic letter.  You can also enter a C statement 
  4246.           at the debuger's "?"  prompt and have it evaluated and the 
  4247.           results displayed, just like in the shell.  
  4248.  
  4249.                We will now walk through a sample program using the 
  4250.           debuger as a way of introducing you to the debuger 
  4251.           commands.  
  4252.  
  4253.  
  4254.  
  4255.  
  4256.  
  4257.  
  4258.                                      - 70 -
  4259.  
  4260.  
  4261.      Small C Interpreter                                Programmer's Manual
  4262.  
  4263.  
  4264.      17.3. Sample Debug Session 
  4265.  
  4266.  
  4267.                If you haven't done so already, list the sample program 
  4268.           that came with your distribution disk, CALC.SCI, either on 
  4269.           your printer or "TYPE" it out on your screen.  This is a 
  4270.           simple integer calculator program that does addition, 
  4271.           subtraction, multiplication and division.  
  4272.  
  4273.                At the shell prompt, load CALC.SCI then type "calc()" 
  4274.           to start the program.  The program displays its prompt (->) 
  4275.           and waits for you to enter a command.  Try entering some 
  4276.           mathematical expressions: 
  4277.  
  4278.  
  4279.                 > load calc.sci
  4280.                 > calc()
  4281.                 -> 2+2
  4282.                 4
  4283.                 -> 2+3*4
  4284.                 14
  4285.                 -> 3*4+2
  4286.                 14
  4287.                 -> 2-30/2
  4288.                 -13
  4289.  
  4290.  
  4291.                Notice that the program is smart enough to know that 
  4292.           multiplication and division have higher precedence than 
  4293.           addition and subtraction.  To get out of the program and 
  4294.           back to the shell, type an "x": 
  4295.  
  4296.  
  4297.                 -> x
  4298.                 0
  4299.                 >
  4300.  
  4301.  
  4302.                Now, let's try the same scenario but this time turn on 
  4303.           the SCI debuger before you start the calculator: 
  4304.  
  4305.  
  4306.                 > trace(1)
  4307.                 0
  4308.                 > calc()
  4309.                 cmd:calc()
  4310.                         ^
  4311.                 ?
  4312.  
  4313.  
  4314.                The debuger displays the C statement you entered on the 
  4315.           shell's command line and prompts you with its "?"  prompt 
  4316.  
  4317.  
  4318.                                      - 71 -
  4319.  
  4320.  
  4321.      Small C Interpreter                                Programmer's Manual
  4322.  
  4323.  
  4324.           and waits for you to enter a command.  For now, just type a 
  4325.           few <RETURN>'s: 
  4326.  
  4327.  
  4328.                 ?
  4329.                  4:calc()
  4330.                        ^
  4331.                 ?
  4332.                  5:{
  4333.                     ^
  4334.                 ?
  4335.                  6:   char line[ 80 ];
  4336.                          ^
  4337.                 ?
  4338.                  8:   Stacktop = 10;
  4339.                               ^
  4340.                 ?
  4341.                  9:   while(1)
  4342.                             ^
  4343.                 ?
  4344.  
  4345.  
  4346.                The program is being executed one line at a time each 
  4347.           time a <RETURN> is hit.  Notice that each line is displayed 
  4348.           preceded by the line number of the program.  The statement 
  4349.           you entered from the shell that started up the calculator is 
  4350.           not a part of the program, and instead was preceded with a 
  4351.           "cmd:" to indicate this fact.  
  4352.  
  4353.  
  4354.      17.3.1. Exiting the Debuger 
  4355.  
  4356.  
  4357.                To halt the program and return back to the shell, use 
  4358.           the debuger's "quit" command: 
  4359.  
  4360.  
  4361.                 ? .q
  4362.                 0
  4363.                 >
  4364.  
  4365.  
  4366.                Now we're back to the shell's prompt.  The ".q" command 
  4367.           stopped the program and turned the debuger off.  Since we 
  4368.           want to experiment some more, turn the debuger back on again 
  4369.           and start up the program: 
  4370.  
  4371.  
  4372.  
  4373.  
  4374.  
  4375.  
  4376.  
  4377.  
  4378.                                      - 72 -
  4379.  
  4380.  
  4381.                Small C Interpreter                                Programmer's Manual
  4382.  
  4383.  
  4384.                 > trace(1)
  4385.                 0
  4386.                 > calc()
  4387.                 cmd:calc()
  4388.                         ^
  4389.                 ?
  4390.  
  4391.  
  4392.  
  4393.      17.3.2. Single Stepping 
  4394.  
  4395.  
  4396.                You can execute more than one program line at a time 
  4397.           with the "step" command.  At the "?"  prompt, type ".s" 
  4398.           followed by the number of program lines you want to execute: 
  4399.  
  4400.  
  4401.                 ? .s 4
  4402.                  9:   while(1)
  4403.                            ^
  4404.                 ?
  4405.  
  4406.  
  4407.                The debuger executed 4 lines, then stopped.  This is 
  4408.           useful when you want to get through a section of code 
  4409.           quickly without having to hit <RETURN> and waiting for each 
  4410.           line to be displayed.  The "continue" command is equivalent 
  4411.           to a ".s" with an infinitely large step count: 
  4412.  
  4413.  
  4414.                 ? .c
  4415.                 -> 2+2
  4416.                 4
  4417.                 ->
  4418.  
  4419.  
  4420.                The program appears to be running slower than when it 
  4421.           was run with the debuger turned off.  This is because the 
  4422.           debuger is still in control of the program, and must examine 
  4423.           each line before it is executed.  The usefulness of the ".c" 
  4424.           command will become apparent later when we discuss 
  4425.           breakpoints.  To return back to the debuger prompt, hit an 
  4426.           <ESCAPE> while the program is running.  If the program is 
  4427.           waiting for input from the console, hitting the <ESCAPE> key 
  4428.           will have no effect.  So type some mathematical expression 
  4429.           as before, hit a <RETURN> and then quickly hit the <ESCAPE> 
  4430.           key: 
  4431.  
  4432.  
  4433.  
  4434.  
  4435.  
  4436.  
  4437.  
  4438.                                      - 73 -
  4439.  
  4440.  
  4441.                Small C Interpreter                                Programmer's Manual
  4442.  
  4443.  
  4444.                 -> 2+3*4
  4445.                 interrupt
  4446.                 36:   while(1)
  4447.                            ^
  4448.                 ?
  4449.  
  4450.  
  4451.                When the <ESCAPE> is hit, the debuger displays an 
  4452.           "interrupt" message, followed by the program line it was 
  4453.           currently working on.  
  4454.  
  4455.  
  4456.      17.3.3. Displaying Global Variables 
  4457.  
  4458.  
  4459.                At any time the debuger is waiting for input you may 
  4460.           display all of the program's global variables and their 
  4461.           contents with the "global" command: 
  4462.  
  4463.  
  4464.                 ? .g
  4465.                    char *Lineptr (0xc334) = "2+3*4"
  4466.                    int   Stack[10] (0xc320) =  4  2  0  0  0  0  0  0  0  0
  4467.                    int   Stackpt = 0
  4468.                    int   Stackto = 10
  4469.                 ?
  4470.  
  4471.  
  4472.                The ".g" command displays each variable along with its 
  4473.           data type ("char" or "int").  If the variable is an array or 
  4474.           a pointer, its address is also printed in hexadecimal, for 
  4475.           example (0xc352). Following that, the variable's value is 
  4476.           displayed.  If the variable is an array or a pointer, the 
  4477.           first ten items in the array are displayed.  Character 
  4478.           arrays are printed as strings, integer arrays as a series of 
  4479.           decimal numbers.  
  4480.  
  4481.                Another form of the ".g" command, ".G", will display 
  4482.           all of the program's functions and their program line 
  4483.           numbers in addition to global variables: 
  4484.  
  4485.  
  4486.  
  4487.  
  4488.  
  4489.  
  4490.  
  4491.  
  4492.  
  4493.  
  4494.  
  4495.  
  4496.  
  4497.  
  4498.                                      - 74 -
  4499.  
  4500.  
  4501.                Small C Interpreter                                Programmer's Manual
  4502.  
  4503.  
  4504.                 ? .G
  4505.                    char *Lineptr (0xc334) = "2+3*4"
  4506.                    int   Stack[10] (0xc320) =  4  2  0  0  0  0  0  0  0  0
  4507.                    int   Stackpt = 0
  4508.                    int   Stackto = 10
  4509.                  4:calc()
  4510.                 22:number()
  4511.                 32:addition()
  4512.                 57:multiplication()
  4513.                 82:push( n )
  4514.                 89:pop()
  4515.                 96:isdigit( c )
  4516.                 ?
  4517.  
  4518.  
  4519.  
  4520.      17.3.4. Breakpoints 
  4521.  
  4522.  
  4523.                Next we will discuss one of the most powerful features 
  4524.           of the debuger: breakpoints.  Let's say we wanted to stop 
  4525.           the program every time the functions "push" and "pop" were 
  4526.           called, so that we could inspect the program's state.  
  4527.           Looking at the debuger's output from the ".G" command above, 
  4528.           we see that these functions are located at lines 82 and 89 
  4529.           respectively.  To set breakpoints at these line numbers, we 
  4530.           would enter the following two commands: 
  4531.  
  4532.  
  4533.                 ? .b 82
  4534.                 breakpoint set:
  4535.                 82:push( n )
  4536.                 ? .b 89
  4537.                 breakpoint set:
  4538.                 89:pop()
  4539.                 ?
  4540.  
  4541.  
  4542.                The debuger prints the program line at which the 
  4543.           breakpoint is set for verification.  
  4544.  
  4545.                You may set a maximum of 5 breakpoints at any one 
  4546.           time.  To display all of the breakpoints that are currently 
  4547.           set, use the ".B" command: 
  4548.  
  4549.  
  4550.                 ? .B
  4551.                 82:push( n )
  4552.                 89:pop()
  4553.                 ?
  4554.  
  4555.  
  4556.  
  4557.  
  4558.                                      - 75 -
  4559.  
  4560.  
  4561.      Small C Interpreter                                Programmer's Manual
  4562.  
  4563.  
  4564.                Now we can continue executing the program normally and 
  4565.           it should stop as soon as either the "push" or "pop" 
  4566.           functions are called.  This is where the ".c" command is 
  4567.           used: 
  4568.  
  4569.  
  4570.                 ? .c
  4571.                 breakpoint:
  4572.                 82:push( n )
  4573.                        ^
  4574.                 ?
  4575.  
  4576.  
  4577.                As soon as a breakpoint is reached, the debuger 
  4578.           announces this fact and displays the program line at the 
  4579.           breakpoint.  To delete a breakpoint, use the "delete 
  4580.           breakpoint" command: 
  4581.  
  4582.  
  4583.                 ? .d 82
  4584.                 breakpoint deleted:
  4585.                 82:push( n )
  4586.                 ?
  4587.  
  4588.  
  4589.                Again, the program line at which the breakpoint was 
  4590.           deleted is displayed for verification.  When a breakpoint is 
  4591.           deleted, the debuger will no longer stop at this program 
  4592.           line after a ".c" command.  
  4593.  
  4594.                To delete all breakpoints set, use the ".D" command: 
  4595.  
  4596.  
  4597.                 ? .D
  4598.                 all breakpoints deleted
  4599.                 ?
  4600.  
  4601.  
  4602.  
  4603.      17.3.5. Function Call Trace Back 
  4604.  
  4605.  
  4606.                Using breakpoints we can be certain of only one fact: 
  4607.           the program started at point "A", and stopped at point "B". 
  4608.           We know nothing about the route it took in getting there.  
  4609.           The debuger's "trace back" command at least tells us the 
  4610.           order of function calls that got us to point "B": Continuing 
  4611.           with our debuging session, type the following command: 
  4612.  
  4613.  
  4614.  
  4615.  
  4616.  
  4617.  
  4618.                                      - 76 -
  4619.  
  4620.  
  4621.                Small C Interpreter                                Programmer's Manual
  4622.  
  4623.  
  4624.                 ? .t
  4625.                 82:push( n )
  4626.                 22:number()
  4627.                 57:multiplication()
  4628.                 32:addition()
  4629.                  4:calc()
  4630.                 ?
  4631.  
  4632.  
  4633.                The function call trace back printed by the ".t" 
  4634.           command is read backwards from bottom to top.  In other 
  4635.           words in the above display, the function "calc" (which is 
  4636.           the starting point) called "addition", which in turn called 
  4637.           "multiplication", and so on.  
  4638.  
  4639.                A variation of the "trace back" command, ".T", will 
  4640.           also display all local variables and their contents for each 
  4641.           function in the trace back: 
  4642.  
  4643.  
  4644.                 ? .T
  4645.                 82:push( n )
  4646.                    int   n = 2
  4647.                 22:number()
  4648.                 57:multiplication()
  4649.                    int   num = 0
  4650.                 32:addition()
  4651.                    int   num = 0
  4652.                  4:calc()
  4653.                    char  line[80] (0xc334) = "2+3*4"
  4654.                 ?
  4655.  
  4656.  
  4657.                The local variables are displayed in a similar format 
  4658.           as for the ".g" command.  
  4659.  
  4660.  
  4661.      17.3.6. Examine a Program 
  4662.  
  4663.  
  4664.                You may also use the SCI editor to examine your 
  4665.           program.  The editor will not allow you make any changes 
  4666.           when invoked from the debuger, since this could completely 
  4667.           alter the state of the current program run.  To "examine" 
  4668.           your program, type: 
  4669.  
  4670.  
  4671.                 ? .e
  4672.  
  4673.  
  4674.                The screen is erased and the editor is started up with 
  4675.           the cursor resting on the line in the program that is to be 
  4676.  
  4677.  
  4678.                                      - 77 -
  4679.  
  4680.  
  4681.      Small C Interpreter                                Programmer's Manual
  4682.  
  4683.  
  4684.           executed next.  You may move about freely in the editor, but 
  4685.           you may not make any changes.  
  4686.  
  4687.                When you exit the editor (with a ^Z) the debuger knows 
  4688.           which line the cursor was on when you left the editor, and 
  4689.           you may set a breakpoint at that line by just giving the 
  4690.                        _______                             ".b" command without a line number.  
  4691.  
  4692.  
  4693.  
  4694.  
  4695.  
  4696.  
  4697.  
  4698.  
  4699.  
  4700.  
  4701.  
  4702.  
  4703.  
  4704.  
  4705.  
  4706.  
  4707.  
  4708.  
  4709.  
  4710.  
  4711.  
  4712.  
  4713.  
  4714.  
  4715.  
  4716.  
  4717.  
  4718.  
  4719.  
  4720.  
  4721.  
  4722.  
  4723.  
  4724.  
  4725.  
  4726.  
  4727.  
  4728.  
  4729.  
  4730.  
  4731.  
  4732.  
  4733.  
  4734.  
  4735.  
  4736.  
  4737.  
  4738.                                      - 78 -
  4739.  
  4740.  
  4741.      Small C Interpreter                                Programmer's Manual
  4742.  
  4743.  
  4744.      18. The Shell 
  4745.  
  4746.  
  4747.                This section will discuss in detail the operation of 
  4748.           the program found in the file SHELL.SCI. We will also show 
  4749.           you how to customize the shell program to suit your needs.  
  4750.  
  4751.                If you haven't done so already, print out the shell 
  4752.           program file or "TYPE" it out on your console screen.  As 
  4753.           you can see there are basically 2 sections of this program: 
  4754.           the first section declares all of the Library Functions 
  4755.           ("sys" call interfaces), The second section starts 
  4756.           immediately after the "entry" keyword with the function 
  4757.           "main()". This is the function that is executed after 
  4758.           SHELL.SCI has been loaded into memory.  Let's examine this 
  4759.           function more closely now: 
  4760.  
  4761.  
  4762.  
  4763.  
  4764.  
  4765.  
  4766.  
  4767.  
  4768.  
  4769.  
  4770.  
  4771.  
  4772.  
  4773.  
  4774.  
  4775.  
  4776.  
  4777.  
  4778.  
  4779.  
  4780.  
  4781.  
  4782.  
  4783.  
  4784.  
  4785.  
  4786.  
  4787.  
  4788.  
  4789.  
  4790.  
  4791.  
  4792.  
  4793.  
  4794.  
  4795.  
  4796.  
  4797.  
  4798.                                      - 79 -
  4799.  
  4800.  
  4801.      Small C Interpreter                                Programmer's Manual
  4802.  
  4803.  
  4804.                43: entry
  4805.                44: 
  4806.                45: char ln[80];
  4807.                46: char pr[20000];
  4808.                47: 
  4809.                48: main()
  4810.                49: {
  4811.                50:    int f, t;
  4812.                51: 
  4813.                52:    puts(sys(0));
  4814.                53:    puts("\nShell V1.3 15Mar86 Copyright (C) 1986 Bob Brodt\n");
  4815.                54:    _nr=25; _nc=80;
  4816.                55:    _ro=_co=1;
  4817.                56:    _cp="\033[%d;%dH";
  4818.                57:    _el="\033[K";
  4819.                58:    _mhz=5; 
  4820.                59:    *pr='Z';
  4821.                60: 
  4822.                61:    for(;;) {
  4823.                62:       puts("> ");
  4824.                63:       ln[5]=0;
  4825.                64:       if(gets(ln)) {
  4826.                65:          if (!strncmp(ln,"edit",4))
  4827.                66:             sys(atoi(ln+4),pr,19);
  4828.                67:          else if (!strncmp(ln,"list",4)) {
  4829.                68:             f=1;
  4830.                69:             t=32765;
  4831.                70:             if(ln[4])
  4832.                71:                sscanf(ln+4,"%d %d",&f,&t);
  4833.                72:             sys(pr,f,t,27);
  4834.                73:          }
  4835.                74:          else if (!strncmp(ln,"save",4))
  4836.                75:             sys(ln+5,pr,26);
  4837.                76:          else if (!strncmp(ln,"load",4))
  4838.                77:             sys(ln+5,pr,25);
  4839.                78:          else if (!strcmp(ln,"exit"))
  4840.                79:             exit();
  4841.                80:          else
  4842.                81:             printf("\n%d\n",sys(ln,pr,16));
  4843.                82:       }
  4844.                83:    }
  4845.                84: }
  4846.  
  4847.  
  4848.                Note that we have included line numbers here for 
  4849.           reference.  
  4850.  
  4851.                The data declarations at lines 45 and 46 are the 
  4852.           shell's input line buffer (ln[80]) and user program buffer 
  4853.           (pr[20000]) respectively.  Lines 52 and 53 of course print 
  4854.           the program identification banners.  Lines 54 through 58 
  4855.           assign the editor's customization variables (for the IBM PC 
  4856.  
  4857.  
  4858.                                      - 80 -
  4859.  
  4860.  
  4861.      Small C Interpreter                                Programmer's Manual
  4862.  
  4863.  
  4864.           in this version).  Line 61 starts a "forever" loop that can 
  4865.           only terminated by the call to the function "exit()" at line 
  4866.           79.  This loop starts out by displaying the shell prompt ("> 
  4867.           ") on the console screen, then waiting for a line of input 
  4868.           from the console keyboard.  The input line buffer stores the 
  4869.           C statement read in from the console at line 64. It is then 
  4870.           compared to each of the strings "edit", "list", "save", 
  4871.           "load" and "exit".  If the first four characters in the 
  4872.           input buffer don't match any of these strings, the line is 
  4873.           assumed to be a C statement and handed off to the 
  4874.           interpreter (via "sys" function 16) for execution.  
  4875.  
  4876.                The program buffer, "pr" is used to store the user's 
  4877.           program functions and variables.  The user can enter data 
  4878.           into this buffer only by way of the SCI program editor 
  4879.           ("sys" function 19).  In fact, the program buffer is 
  4880.           completely hidden from the user - any attempt to reference 
  4881.           it via a C statement (for example "putchar( pr[0] )") will 
  4882.           result in an "undefined symbol" error message.  The user's 
  4883.           program in the "pr" buffer is in "tokenized" form.  That is, 
  4884.           each language element (variables, keywords, punctuation, 
  4885.           etc.) has been encoded so that it can be more easily and 
  4886.           quickly recognized by the interpreter.  The tokenized form 
  4887.           of a program bears almost no resemblance to the 
  4888.           human-readable form and should not be tampered with.  
  4889.  
  4890.  
  4891.      18.1. Customizing the Shell 
  4892.  
  4893.  
  4894.                Now we will show you how you can customize this 
  4895.           program.  Start up SCI and when the shell's prompt appears, 
  4896.           enter the command: 
  4897.  
  4898.  
  4899.                > load shell.sci
  4900.  
  4901.           
  4902.           to load the shell file.  Now edit the program from SCI's 
  4903.           editor and remove all lines from the beginning of the 
  4904.           program up to and including the "entry" keyword.  Next let's 
  4905.           change the string on line 62 (above) to something like: 
  4906.           "yes, dear?  ".  Finally, replace the "exit()" on line 79 
  4907.           with a "return".  
  4908.  
  4909.                Exit the editor and from the shell prompt type: 
  4910.  
  4911.  
  4912.                > main()
  4913.  
  4914.  
  4915.                You should see the program identification banner again 
  4916.  
  4917.  
  4918.                                      - 81 -
  4919.  
  4920.  
  4921.      Small C Interpreter                                Programmer's Manual
  4922.  
  4923.  
  4924.           and the new shell's prompt, "yes, dear?  "!  You can now do 
  4925.           everything from this new shell that you did from the 
  4926.           original shell - write programs with the editor, save them, 
  4927.           list them and load them.  When you type "exit" to this new 
  4928.           shell however, you are returned to the original shell 
  4929.           because we replaced the "exit to DOS" function call with a 
  4930.           "return" to caller.  Since the caller was the original 
  4931.           shell, you are returned to its "> " prompt.  
  4932.  
  4933.                Type an "exit" now to get back to the first shell and 
  4934.           from there do a "save newshell".  Then type "main()" again 
  4935.           to get the "yes, dear?  " shell.  From here, type "load 
  4936.           newshell" to load the newshell program.  Edit the newshell 
  4937.           program and change the "yes, dear?  " prompt to something 
  4938.           like: "you again?  ". Now exit the editor and at the "yes, 
  4939.           dear?  " prompt type "main()". You should again see the 
  4940.           program logon banner and the new shell prompt "you again?  
  4941.           ", like this: 
  4942.  
  4943.  
  4944.                yes, dear? main()
  4945.                Small C Interpreter V1.3 15Mar86 Copyright (C) 1986 Bob Brodt
  4946.                Shell V1.3 15Mar86 Copyright (C) 1986 Bob Brodt
  4947.                you again?
  4948.  
  4949.  
  4950.                In all, we now have 3 different shell programs running, 
  4951.           one on top of the other, and we could actually continue 
  4952.           doing this until we run out of memory!  This is exactly 
  4953.           analagous to the layers of an onion: each layer gets smaller 
  4954.           as you go towards the center of the onion, just as the 
  4955.           amount of usable memory becomes less as each new shell 
  4956.           program is loaded from the previous shell.  
  4957.  
  4958.                Now return to the original shell like so: 
  4959.  
  4960.  
  4961.                you again? exit
  4962.                0
  4963.                yes, dear? exit
  4964.                0
  4965.                >
  4966.  
  4967.  
  4968.                It now becomes an easy task to customize the shell 
  4969.           program to your heart's content using the SCI editor, test 
  4970.           it from the SCI interpreter environment and when it's fully 
  4971.           debuged, save it to disk.  Of course you must remember to 
  4972.           insert the Library Function declarations and the "entry" 
  4973.           keyword before the new shell "main()" function if you intend 
  4974.           to replace SHELL.SCI with the new program.  
  4975.  
  4976.  
  4977.  
  4978.                                      - 82 -
  4979.  
  4980.  
  4981.      Small C Interpreter                                Programmer's Manual
  4982.  
  4983.  
  4984.                As an exercise, add a directory listing command to the 
  4985.           shell, using the following program as a guide.  If are 
  4986.           having difficulty, you may peek at the answers on the next 
  4987.           page...  
  4988.  
  4989.  
  4990.                dir(pat)
  4991.                {
  4992.                     char file[16];
  4993.                     int t;
  4994.                
  4995.                     t=0;
  4996.                     if(pat)
  4997.                          f=scandir(pat,file);
  4998.                     else
  4999.                          f=scandir("*.*",file);
  5000.                     while(f) {
  5001.                          printf("%-20s",file);
  5002.                          ++t;
  5003.                          f=scandir(0,file);
  5004.                     }
  5005.                     if(t%4)
  5006.                          putchar('\n');
  5007.                }
  5008.  
  5009.  
  5010.  
  5011.  
  5012.  
  5013.  
  5014.  
  5015.  
  5016.  
  5017.  
  5018.  
  5019.  
  5020.  
  5021.  
  5022.  
  5023.  
  5024.  
  5025.  
  5026.  
  5027.  
  5028.  
  5029.  
  5030.  
  5031.  
  5032.  
  5033.  
  5034.  
  5035.  
  5036.  
  5037.  
  5038.                                      - 83 -
  5039.  
  5040.  
  5041.      Small C Interpreter                                Programmer's Manual
  5042.  
  5043.  
  5044.                     .
  5045.                     .
  5046.                     .
  5047.                     exit();
  5048.                else if (!strncmp(ln,"dir",3)) {
  5049.                     char file[16];
  5050.                
  5051.                     t=0;
  5052.                     if(ln[3]) f=scandir(ln+4,file);
  5053.                     else f=scandir("*.*",file);
  5054.                     while(f) {
  5055.                          printf("%-20s",file);
  5056.                          ++t;
  5057.                          f=scandir(0,file);
  5058.                     }
  5059.                     if(t%4) putchar('\n');
  5060.                }
  5061.                else
  5062.                     .
  5063.                     .
  5064.                     .
  5065.  
  5066.  
  5067.  
  5068.      18.2. DOS Command Line Arguments to the Shell 
  5069.  
  5070.  
  5071.                A mechanism has been provided to pass operating system 
  5072.           command line arguments to the shell in a way similar to most 
  5073.           commercially available C compilers.  By specifying a "-A" on 
  5074.           the MS-DOS command lines, all arguments to the right of the 
  5075.           "-A" will be ignored by SCI and instead passed to the shell 
  5076.           program.  
  5077.  
  5078.                SCI always passes two arguments to the "entry" program 
  5079.           in the startup file, although the program is free to use or 
  5080.           ignore these arguments.  These are: a count of the number of 
  5081.           arguments following the "-A" option on the DOS command line 
  5082.           and; A pointer to the array of strings that contain these 
  5083.           arguments.  These arguments are commonly declared as "argc" 
  5084.           (argument count) and "argv" (argument vector) in the C 
  5085.           community.  
  5086.  
  5087.                Make the following changes and additions to the program 
  5088.           in SHELL.SCI: 
  5089.  
  5090.  
  5091.  
  5092.  
  5093.  
  5094.  
  5095.  
  5096.  
  5097.  
  5098.                                      - 84 -
  5099.  
  5100.  
  5101.      Small C Interpreter                                Programmer's Manual
  5102.  
  5103.  
  5104.                     .
  5105.                     .
  5106.                     .
  5107.                main(argc, arv)
  5108.                int argc, *argv;
  5109.                {
  5110.                     int i;
  5111.                
  5112.                     while ( i<argc )
  5113.                     {
  5114.                          puts(argv[i++]);
  5115.                          putchar('\n');
  5116.                     }
  5117.                     .
  5118.                     .
  5119.                     .
  5120.                }
  5121.  
  5122.  
  5123.                Then, when the following command is entered at the 
  5124.           operating system level: 
  5125.  
  5126.  
  5127.                A>SCI -A Hello out there!
  5128.  
  5129.           
  5130.           the shell program would start up like this: 
  5131.  
  5132.  
  5133.                Hello
  5134.                out
  5135.                there!
  5136.                Small C Interpreter V1.3M 15Mar86 Copyright (C) 1986 Bob Brodt
  5137.                Shell V1.3M 15Mar86 Copyright (C) 1986 Bob Brodt
  5138.                >
  5139.  
  5140.  
  5141.                Note that since SCI does not support pointers to 
  5142.           pointers, the "argv" variable must be declared as a pointer 
  5143.           to "int". Then, each "argv[i]" is a pointer to a string that 
  5144.           points to one of the words passed on the command line.  
  5145.  
  5146.  
  5147.  
  5148.  
  5149.  
  5150.  
  5151.  
  5152.  
  5153.  
  5154.  
  5155.  
  5156.  
  5157.  
  5158.                                      - 85 -
  5159.  
  5160. əəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəəə